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.9 2004/09/15 15:22:02 joerg 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))
458 /* initialize ffdc values */
459 microtime(&sc->ffdc_resettime);
460 sc->ffdc_resetcount = 1;
461 if ((i = ips_ffdc_reset(sc)) != 0) {
462 device_printf(sc->dev,
463 "failed to send ffdc reset to device (%d)\n", i);
466 if ((i = ips_get_adapter_info(sc)) != 0) {
467 device_printf(sc->dev, "failed to get adapter configuration "
468 "data from device (%d)\n", i);
471 /* no error check as failure doesn't matter */
472 ips_update_nvram(sc);
473 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
474 device_printf(sc->dev, "adapter type: %s\n",
475 ips_adapter_name[sc->adapter_type]);
477 if ((i = ips_get_drive_info(sc)) != 0) {
478 device_printf(sc->dev, "failed to get drive "
479 "configuration data from device (%d)\n", i);
482 ips_cmdqueue_free(sc);
483 if (sc->adapter_info.max_concurrent_cmds)
484 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
487 if (ips_cmdqueue_init(sc)) {
488 device_printf(sc->dev,
489 "failed to initialize command buffers\n");
492 cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
493 dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
494 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
495 "ips%d", device_get_unit(sc->dev));
497 ips_diskdev_init(sc);
498 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
501 ips_adapter_free(sc);
506 * see if we should reinitialize the card and wait for it to timeout
507 * or complete initialization
510 ips_morpheus_reinit(ips_softc_t *sc, int force)
515 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
516 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
517 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
518 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
521 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
522 ips_read_4(sc, MORPHEUS_REG_OIMR);
523 device_printf(sc->dev,
524 "resetting adapter, this may take up to 5 minutes\n");
525 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
527 pci_read_config(sc->dev, 0, 4);
528 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
529 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
531 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
532 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
534 if (tmp & MORPHEUS_BIT_POST1)
535 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
537 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
538 device_printf(sc->dev,
539 "Adapter error during initialization.\n");
542 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
544 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
545 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
547 if (tmp & MORPHEUS_BIT_POST2)
548 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
550 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
551 device_printf(sc->dev, "adapter failed config check\n");
554 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
555 if (force && ips_clear_adapter(sc)) {
556 device_printf(sc->dev, "adapter clear failed\n");
562 /* clean up so we can unload the driver. */
564 ips_adapter_free(ips_softc_t *sc)
568 if (sc->state & IPS_DEV_OPEN)
570 if ((error = ips_diskdev_free(sc)))
572 if (ips_cmdqueue_free(sc)) {
573 device_printf(sc->dev,
574 "trying to exit when command queue is not empty!\n");
577 DEVICE_PRINTF(1, sc->dev, "free\n");
579 callout_stop(&sc->timer);
583 bus_dma_tag_destroy(sc->sg_dmatag);
584 if (sc->command_dmatag)
585 bus_dma_tag_destroy(sc->command_dmatag);
586 cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
591 ips_morpheus_intr(void *void_sc)
593 ips_softc_t *sc = (ips_softc_t *)void_sc;
594 u_int32_t oisr, iisr;
595 ips_cmd_status_t status;
596 ips_command_t *command;
599 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
600 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
601 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
602 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
603 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
606 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
608 cmdnumber = status.fields.command_id;
609 command = &sc->commandarray[cmdnumber];
610 command->status.value = status.value;
611 command->timeout = 0;
612 command->callback(command);
613 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
619 ips_issue_morpheus_cmd(ips_command_t *command)
624 /* hmmm, is there a cleaner way to do this? */
625 if (command->sc->state & IPS_OFFLINE) {
627 command->status.value = IPS_ERROR_STATUS;
628 command->callback(command);
631 command->timeout = 10;
632 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
637 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
638 int segnum, int error)
640 ips_copper_queue_t *queue = queueptr;
644 queue->base_phys_addr = segments[0].ds_addr;
648 ips_copperhead_queue_init(ips_softc_t *sc)
650 bus_dma_tag_t dmatag;
654 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
657 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
658 /* highaddr */ BUS_SPACE_MAXADDR,
660 /* filterarg */ NULL,
661 /* maxsize */ sizeof(ips_copper_queue_t),
663 /* maxsegsize*/ sizeof(ips_copper_queue_t),
666 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
670 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
671 BUS_DMA_NOWAIT, &dmamap)) {
675 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
676 sc->copper_queue->dmatag = dmatag;
677 sc->copper_queue->dmamap = dmamap;
678 sc->copper_queue->nextstatus = 1;
679 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
680 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
681 sc->copper_queue, BUS_DMA_NOWAIT);
682 if (sc->copper_queue->base_phys_addr == 0) {
686 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
687 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
688 IPS_MAX_CMD_NUM * 4);
689 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
690 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
693 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
694 bus_dma_tag_destroy(dmatag);
699 * see if we should reinitialize the card and wait for it to timeout or
700 * complete initialization FIXME
703 ips_copperhead_reinit(ips_softc_t *sc, int force)
705 u_int32_t postcode = 0, configstatus = 0;
708 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
709 ips_write_1(sc, COPPER_REG_SCPR, 0);
710 device_printf(sc->dev,
711 "reinitializing adapter, this could take several minutes.\n");
712 for (j = 0; j < 2; j++) {
714 for (i = 0; i < 45; i++) {
715 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
716 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
717 ips_write_1(sc, COPPER_REG_HISR,
726 for (j = 0; j < 2; j++) {
728 for (i = 0; i < 240; i++) {
729 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
730 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
731 ips_write_1(sc, COPPER_REG_HISR,
740 for (i = 0; i < 240; i++) {
741 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
748 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
749 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
750 ips_copperhead_queue_init(sc);
751 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
752 i = ips_read_1(sc, COPPER_REG_SCPR);
753 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
754 if (configstatus == 0) {
755 device_printf(sc->dev, "adapter initialization failed\n");
758 if (force && ips_clear_adapter(sc)) {
759 device_printf(sc->dev, "adapter clear failed\n");
766 ips_copperhead_cmd_status(ips_softc_t *sc)
772 statnum = sc->copper_queue->nextstatus++;
773 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
774 sc->copper_queue->nextstatus = 0;
776 value = sc->copper_queue->status[statnum];
777 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
784 ips_copperhead_intr(void *void_sc)
786 ips_softc_t *sc = (ips_softc_t *)void_sc;
787 ips_cmd_status_t status;
790 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
791 status.value = ips_copperhead_cmd_status(sc);
792 cmdnumber = status.fields.command_id;
793 sc->commandarray[cmdnumber].status.value = status.value;
794 sc->commandarray[cmdnumber].timeout = 0;
795 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
796 PRINTF(9, "ips: got command %d\n", cmdnumber);
802 ips_issue_copperhead_cmd(ips_command_t *command)
808 /* hmmm, is there a cleaner way to do this? */
809 if (command->sc->state & IPS_OFFLINE) {
811 command->status.value = IPS_ERROR_STATUS;
812 command->callback(command);
815 command->timeout = 10;
816 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
819 printf("sem bit still set, can't send a command\n");
823 DELAY(500); /* need to do a delay here */
825 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
826 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);