2 * Written by: David Jeffery
3 * Copyright (c) 2002 Adaptec Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.10 2004/12/10 04:09:46 y0netan1 Exp $
31 #include <dev/raid/ips/ips.h>
34 #include <machine/clock.h>
36 static d_open_t ips_open;
37 static d_close_t ips_close;
38 static d_ioctl_t ips_ioctl;
40 MALLOC_DEFINE(M_IPSBUF, "ipsbuf", "IPS driver buffer");
42 static struct cdevsw ips_cdevsw = {
44 .d_maj = IPS_CDEV_MAJOR,
49 .old_close = ips_close,
50 .old_ioctl = ips_ioctl,
53 static const char *ips_adapter_name[] = {
55 "ServeRAID (copperhead)",
56 "ServeRAID II (copperhead refresh)",
57 "ServeRAID onboard (copperhead)",
58 "ServeRAID onboard (copperhead)",
59 "ServeRAID 3H (clarinet)",
60 "ServeRAID 3L (clarinet lite)",
61 "ServeRAID 4H (trombone)",
62 "ServeRAID 4M (morpheus)",
63 "ServeRAID 4L (morpheus lite)",
64 "ServeRAID 4Mx (neo)",
65 "ServeRAID 4Lx (neo lite)",
66 "ServeRAID 5i II (sarasota)",
67 "ServeRAID 5i (sarasota)",
68 "ServeRAID 6M (marco)",
69 "ServeRAID 6i (sebring)"
74 ips_open(dev_t dev, int flags, int fmt, d_thread_t *td)
76 ips_softc_t *sc = dev->si_drv1;
78 sc->state |= IPS_DEV_OPEN;
83 ips_close(dev_t dev, int flags, int fmt, d_thread_t *td)
85 ips_softc_t *sc = dev->si_drv1;
87 sc->state &= ~IPS_DEV_OPEN;
92 ips_ioctl(dev_t dev, u_long command, caddr_t addr, int32_t flags,
98 return ips_ioctl_request(sc, command, addr, flags);
102 ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments, int segnum,
105 ips_command_t *command = cmdptr;
107 PRINTF(10, "ips: in ips_cmd_dmaload\n");
109 command->command_phys_addr = segments[0].ds_addr;
113 /* is locking needed? what locking guarentees are there on removal? */
114 static __inline__ int
115 ips_cmdqueue_free(ips_softc_t *sc)
118 ips_command_t *command;
122 if (sc->used_commands == 0) {
123 for (i = 0; i < sc->max_cmds; i++) {
124 command = &sc->commandarray[i];
125 if (command->command_phys_addr == 0)
127 bus_dmamap_unload(sc->command_dmatag,
128 command->command_dmamap);
129 bus_dmamem_free(sc->command_dmatag,
130 command->command_buffer,
131 command->command_dmamap);
134 sc->state |= IPS_OFFLINE;
140 /* places all ips command structs on the free command queue. No locking as if someone else tries
141 * to access this during init, we have bigger problems */
142 static __inline__ int
143 ips_cmdqueue_init(ips_softc_t *sc)
146 ips_command_t *command;
148 SLIST_INIT(&sc->free_cmd_list);
149 STAILQ_INIT(&sc->cmd_wait_list);
150 for (i = 0; i < sc->max_cmds; i++) {
151 command = &sc->commandarray[i];
154 if (bus_dmamem_alloc(sc->command_dmatag,
155 &command->command_buffer, BUS_DMA_NOWAIT,
156 &command->command_dmamap))
158 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
159 command->command_buffer, IPS_COMMAND_LEN, ips_cmd_dmaload,
160 command, BUS_DMA_NOWAIT);
161 if (command->command_phys_addr == 0) {
162 bus_dmamem_free(sc->command_dmatag,
163 command->command_buffer, command->command_dmamap);
166 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
168 sc->state &= ~IPS_OFFLINE;
171 ips_cmdqueue_free(sc);
176 ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *),
180 ips_command_t *command;
181 ips_wait_list_t *waiter;
183 waiter = malloc(sizeof(ips_wait_list_t), M_IPSBUF, M_INTWAIT);
185 if (sc->state & IPS_OFFLINE) {
187 free(waiter, M_IPSBUF);
190 command = SLIST_FIRST(&sc->free_cmd_list);
191 if (command && !(sc->state & IPS_TIMEOUT)) {
192 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
195 clear_ips_command(command);
196 bzero(command->command_buffer, IPS_COMMAND_LEN);
197 free(waiter, M_IPSBUF);
199 return callback(command);
201 DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
202 waiter->callback = callback;
204 STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
210 ips_run_waiting_command(ips_softc_t *sc)
212 ips_wait_list_t *waiter;
213 ips_command_t *command;
214 int (*callback)(ips_command_t*);
218 waiter = STAILQ_FIRST(&sc->cmd_wait_list);
219 command = SLIST_FIRST(&sc->free_cmd_list);
220 if (waiter == NULL || command == NULL) {
224 DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
225 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
226 STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
229 clear_ips_command(command);
230 bzero(command->command_buffer, IPS_COMMAND_LEN);
231 command->arg = waiter->data;
232 callback = waiter->callback;
233 free(waiter, M_IPSBUF);
239 * returns a free command struct if one is available.
240 * It also blanks out anything that may be a wild pointer/value.
241 * Also, command buffers are not freed. They are
242 * small so they are saved and kept dmamapped and loaded.
245 ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data,
248 ips_command_t *command;
252 if (sc->state & IPS_OFFLINE) {
256 command = SLIST_FIRST(&sc->free_cmd_list);
257 if (!command || (sc->state & IPS_TIMEOUT)) {
259 if (flags & IPS_NOWAIT_FLAG)
261 return ips_add_waiting_command(sc, callback, data);
263 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
266 clear_ips_command(command);
267 bzero(command->command_buffer, IPS_COMMAND_LEN);
269 return callback(command);
272 /* adds a command back to the free command queue */
274 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
279 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
282 if (!(sc->state & IPS_TIMEOUT))
283 ips_run_waiting_command(sc);
286 ips_diskdev_statename(u_int8_t state)
288 static char statebuf[20];
297 case IPS_LD_DEGRADED:
310 sprintf(statebuf, "UNKNOWN(0x%02x)", state);
315 ips_diskdev_init(ips_softc_t *sc)
319 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
320 if (sc->drives[i].state == IPS_LD_FREE)
322 device_printf(sc->dev,
323 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
324 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
325 ips_diskdev_statename(sc->drives[i].state));
326 if (sc->drives[i].state == IPS_LD_OKAY ||
327 sc->drives[i].state == IPS_LD_DEGRADED) {
328 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
329 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
332 if (bus_generic_attach(sc->dev))
333 device_printf(sc->dev, "Attaching bus failed\n");
338 ips_diskdev_free(ips_softc_t *sc)
343 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
344 if (sc->diskdev[i] != NULL) {
345 error = device_delete_child(sc->dev, sc->diskdev[i]);
350 bus_generic_detach(sc->dev);
355 * ips_timeout is periodically called to make sure no commands sent
356 * to the card have become stuck. If it finds a stuck command, it
357 * sets a flag so the driver won't start any more commands and then
358 * is periodically called to see if all outstanding commands have
359 * either finished or timed out. Once timed out, an attempt to
360 * reinitialize the card is made. If that fails, the driver gives
361 * up and declares the card dead.
364 ips_timeout(void *arg)
366 ips_command_t *command;
367 ips_softc_t *sc = arg;
371 command = &sc->commandarray[0];
373 for (i = 0; i < sc->max_cmds; i++) {
374 if (!command[i].timeout)
376 command[i].timeout--;
377 if (command[i].timeout == 0) {
378 if (!(sc->state & IPS_TIMEOUT)) {
379 sc->state |= IPS_TIMEOUT;
380 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
382 command[i].status.value = IPS_ERROR_STATUS;
383 command[i].callback(&command[i]);
384 /* hmm, this should be enough cleanup */
388 if (!state && (sc->state & IPS_TIMEOUT)) {
389 if (sc->ips_adapter_reinit(sc, 1)) {
390 device_printf(sc->dev, "AIEE! adapter reset failed, "
391 "giving up and going home! Have a nice day.\n");
392 sc->state |= IPS_OFFLINE;
393 sc->state &= ~IPS_TIMEOUT;
395 * Grr, I hate this solution. I run waiting commands
396 * one at a time and error them out just before they
397 * would go to the card. This sucks.
400 sc->state &= ~IPS_TIMEOUT;
401 ips_run_waiting_command(sc);
403 if (sc->state != IPS_OFFLINE)
404 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
408 /* check card and initialize it */
410 ips_adapter_init(ips_softc_t *sc)
415 DEVICE_PRINTF(1, sc->dev, "initializing\n");
416 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
419 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
420 /* highaddr */ BUS_SPACE_MAXADDR,
422 /* filterarg */ NULL,
423 /* maxsize */ IPS_COMMAND_LEN +
426 /* maxsegsize*/ IPS_COMMAND_LEN +
429 &sc->command_dmatag) != 0) {
430 device_printf(sc->dev, "can't alloc command dma tag\n");
433 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
436 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
437 /* highaddr */ BUS_SPACE_MAXADDR,
439 /* filterarg */ NULL,
440 /* maxsize */ IPS_MAX_IOBUF_SIZE,
441 /* numsegs */ IPS_MAX_SG_ELEMENTS,
442 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
444 &sc->sg_dmatag) != 0) {
445 device_printf(sc->dev, "can't alloc SG dma tag\n");
449 * create one command buffer until we know how many commands this card
453 ips_cmdqueue_init(sc);
454 callout_init(&sc->timer);
455 if (sc->ips_adapter_reinit(sc, 0))
457 /* initialize ffdc values */
458 microtime(&sc->ffdc_resettime);
459 sc->ffdc_resetcount = 1;
460 if ((i = ips_ffdc_reset(sc)) != 0) {
461 device_printf(sc->dev,
462 "failed to send ffdc reset to device (%d)\n", i);
465 if ((i = ips_get_adapter_info(sc)) != 0) {
466 device_printf(sc->dev, "failed to get adapter configuration "
467 "data from device (%d)\n", i);
470 /* no error check as failure doesn't matter */
471 ips_update_nvram(sc);
472 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
473 device_printf(sc->dev, "adapter type: %s\n",
474 ips_adapter_name[sc->adapter_type]);
476 if ((i = ips_get_drive_info(sc)) != 0) {
477 device_printf(sc->dev, "failed to get drive "
478 "configuration data from device (%d)\n", i);
481 ips_cmdqueue_free(sc);
482 if (sc->adapter_info.max_concurrent_cmds)
483 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
486 if (ips_cmdqueue_init(sc)) {
487 device_printf(sc->dev,
488 "failed to initialize command buffers\n");
491 cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
492 dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
493 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
494 "ips%d", device_get_unit(sc->dev));
496 ips_diskdev_init(sc);
497 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
500 ips_adapter_free(sc);
505 * see if we should reinitialize the card and wait for it to timeout
506 * or complete initialization
509 ips_morpheus_reinit(ips_softc_t *sc, int force)
514 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
515 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
516 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
517 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
520 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
521 ips_read_4(sc, MORPHEUS_REG_OIMR);
522 device_printf(sc->dev,
523 "resetting adapter, this may take up to 5 minutes\n");
524 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
526 pci_read_config(sc->dev, 0, 4);
527 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
528 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
530 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
531 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
533 if (tmp & MORPHEUS_BIT_POST1)
534 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
536 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
537 device_printf(sc->dev,
538 "Adapter error during initialization.\n");
541 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
543 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
544 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
546 if (tmp & MORPHEUS_BIT_POST2)
547 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
549 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
550 device_printf(sc->dev, "adapter failed config check\n");
553 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
554 if (force && ips_clear_adapter(sc)) {
555 device_printf(sc->dev, "adapter clear failed\n");
561 /* clean up so we can unload the driver. */
563 ips_adapter_free(ips_softc_t *sc)
567 if (sc->state & IPS_DEV_OPEN)
569 if ((error = ips_diskdev_free(sc)))
571 if (ips_cmdqueue_free(sc)) {
572 device_printf(sc->dev,
573 "trying to exit when command queue is not empty!\n");
576 DEVICE_PRINTF(1, sc->dev, "free\n");
578 callout_stop(&sc->timer);
581 bus_dma_tag_destroy(sc->sg_dmatag);
582 if (sc->command_dmatag)
583 bus_dma_tag_destroy(sc->command_dmatag);
584 cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
589 ips_morpheus_intr(void *void_sc)
591 ips_softc_t *sc = (ips_softc_t *)void_sc;
592 u_int32_t oisr, iisr;
593 ips_cmd_status_t status;
594 ips_command_t *command;
597 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
598 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
599 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
600 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
601 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
604 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
606 cmdnumber = status.fields.command_id;
607 command = &sc->commandarray[cmdnumber];
608 command->status.value = status.value;
609 command->timeout = 0;
610 command->callback(command);
611 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
617 ips_issue_morpheus_cmd(ips_command_t *command)
622 /* hmmm, is there a cleaner way to do this? */
623 if (command->sc->state & IPS_OFFLINE) {
625 command->status.value = IPS_ERROR_STATUS;
626 command->callback(command);
629 command->timeout = 10;
630 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
635 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
636 int segnum, int error)
638 ips_copper_queue_t *queue = queueptr;
642 queue->base_phys_addr = segments[0].ds_addr;
646 ips_copperhead_queue_init(ips_softc_t *sc)
648 bus_dma_tag_t dmatag;
652 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
655 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
656 /* highaddr */ BUS_SPACE_MAXADDR,
658 /* filterarg */ NULL,
659 /* maxsize */ sizeof(ips_copper_queue_t),
661 /* maxsegsize*/ sizeof(ips_copper_queue_t),
664 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
668 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
669 BUS_DMA_NOWAIT, &dmamap)) {
673 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
674 sc->copper_queue->dmatag = dmatag;
675 sc->copper_queue->dmamap = dmamap;
676 sc->copper_queue->nextstatus = 1;
677 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
678 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
679 sc->copper_queue, BUS_DMA_NOWAIT);
680 if (sc->copper_queue->base_phys_addr == 0) {
684 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
685 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
686 IPS_MAX_CMD_NUM * 4);
687 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
688 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
691 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
692 bus_dma_tag_destroy(dmatag);
697 * see if we should reinitialize the card and wait for it to timeout or
698 * complete initialization FIXME
701 ips_copperhead_reinit(ips_softc_t *sc, int force)
703 u_int32_t postcode = 0, configstatus = 0;
706 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
707 ips_write_1(sc, COPPER_REG_SCPR, 0);
708 device_printf(sc->dev,
709 "reinitializing adapter, this could take several minutes.\n");
710 for (j = 0; j < 2; j++) {
712 for (i = 0; i < 45; i++) {
713 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
714 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
715 ips_write_1(sc, COPPER_REG_HISR,
724 for (j = 0; j < 2; j++) {
726 for (i = 0; i < 240; i++) {
727 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
728 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
729 ips_write_1(sc, COPPER_REG_HISR,
738 for (i = 0; i < 240; i++) {
739 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
746 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
747 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
748 ips_copperhead_queue_init(sc);
749 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
750 i = ips_read_1(sc, COPPER_REG_SCPR);
751 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
752 if (configstatus == 0) {
753 device_printf(sc->dev, "adapter initialization failed\n");
756 if (force && ips_clear_adapter(sc)) {
757 device_printf(sc->dev, "adapter clear failed\n");
764 ips_copperhead_cmd_status(ips_softc_t *sc)
770 statnum = sc->copper_queue->nextstatus++;
771 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
772 sc->copper_queue->nextstatus = 0;
774 value = sc->copper_queue->status[statnum];
775 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
782 ips_copperhead_intr(void *void_sc)
784 ips_softc_t *sc = (ips_softc_t *)void_sc;
785 ips_cmd_status_t status;
788 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
789 status.value = ips_copperhead_cmd_status(sc);
790 cmdnumber = status.fields.command_id;
791 sc->commandarray[cmdnumber].status.value = status.value;
792 sc->commandarray[cmdnumber].timeout = 0;
793 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
794 PRINTF(9, "ips: got command %d\n", cmdnumber);
800 ips_issue_copperhead_cmd(ips_command_t *command)
806 /* hmmm, is there a cleaner way to do this? */
807 if (command->sc->state & IPS_OFFLINE) {
809 command->status.value = IPS_ERROR_STATUS;
810 command->callback(command);
813 command->timeout = 10;
814 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
817 printf("sem bit still set, can't send a command\n");
821 DELAY(500); /* need to do a delay here */
823 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
824 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);