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.11 2005/06/07 00:51:13 y0netan1 Exp $
31 #include <dev/raid/ips/ips.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 cdevsw ips_cdevsw = {
45 .d_maj = IPS_CDEV_MAJOR,
50 .old_close = ips_close,
51 .old_ioctl = ips_ioctl,
54 static const char *ips_adapter_name[] = {
56 "ServeRAID (copperhead)",
57 "ServeRAID II (copperhead refresh)",
58 "ServeRAID onboard (copperhead)",
59 "ServeRAID onboard (copperhead)",
60 "ServeRAID 3H (clarinet)",
61 "ServeRAID 3L (clarinet lite)",
62 "ServeRAID 4H (trombone)",
63 "ServeRAID 4M (morpheus)",
64 "ServeRAID 4L (morpheus lite)",
65 "ServeRAID 4Mx (neo)",
66 "ServeRAID 4Lx (neo lite)",
67 "ServeRAID 5i II (sarasota)",
68 "ServeRAID 5i (sarasota)",
69 "ServeRAID 6M (marco)",
70 "ServeRAID 6i (sebring)"
75 ips_open(dev_t dev, int flags, int fmt, d_thread_t *td)
77 ips_softc_t *sc = dev->si_drv1;
79 sc->state |= IPS_DEV_OPEN;
84 ips_close(dev_t dev, int flags, int fmt, d_thread_t *td)
86 ips_softc_t *sc = dev->si_drv1;
88 sc->state &= ~IPS_DEV_OPEN;
93 ips_ioctl(dev_t dev, u_long command, caddr_t addr, int32_t flags,
99 return ips_ioctl_request(sc, command, addr, flags);
103 ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments, int segnum,
106 ips_command_t *command = cmdptr;
108 PRINTF(10, "ips: in ips_cmd_dmaload\n");
110 command->command_phys_addr = segments[0].ds_addr;
114 /* is locking needed? what locking guarentees are there on removal? */
115 static __inline__ int
116 ips_cmdqueue_free(ips_softc_t *sc)
119 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 *),
179 ips_command_t *command;
180 ips_wait_list_t *waiter;
182 waiter = malloc(sizeof(ips_wait_list_t), M_IPSBUF, M_INTWAIT);
184 if (sc->state & IPS_OFFLINE) {
186 free(waiter, M_IPSBUF);
189 command = SLIST_FIRST(&sc->free_cmd_list);
190 if (command && !(sc->state & IPS_TIMEOUT)) {
191 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
194 clear_ips_command(command);
195 bzero(command->command_buffer, IPS_COMMAND_LEN);
196 free(waiter, M_IPSBUF);
198 return callback(command);
200 DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
201 waiter->callback = callback;
203 STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
209 ips_run_waiting_command(ips_softc_t *sc)
211 ips_wait_list_t *waiter;
212 ips_command_t *command;
213 int (*callback)(ips_command_t*);
216 waiter = STAILQ_FIRST(&sc->cmd_wait_list);
217 command = SLIST_FIRST(&sc->free_cmd_list);
218 if (waiter == NULL || command == NULL) {
222 DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
223 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
224 STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
227 clear_ips_command(command);
228 bzero(command->command_buffer, IPS_COMMAND_LEN);
229 command->arg = waiter->data;
230 callback = waiter->callback;
231 free(waiter, M_IPSBUF);
237 * returns a free command struct if one is available.
238 * It also blanks out anything that may be a wild pointer/value.
239 * Also, command buffers are not freed. They are
240 * small so they are saved and kept dmamapped and loaded.
243 ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data,
246 ips_command_t *command;
249 if (sc->state & IPS_OFFLINE) {
253 command = SLIST_FIRST(&sc->free_cmd_list);
254 if (!command || (sc->state & IPS_TIMEOUT)) {
256 if (flags & IPS_NOWAIT_FLAG)
258 return ips_add_waiting_command(sc, callback, data);
260 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
263 clear_ips_command(command);
264 bzero(command->command_buffer, IPS_COMMAND_LEN);
266 return callback(command);
269 /* adds a command back to the free command queue */
271 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
274 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
277 if (!(sc->state & IPS_TIMEOUT))
278 ips_run_waiting_command(sc);
281 ips_diskdev_statename(u_int8_t state)
283 static char statebuf[20];
292 case IPS_LD_DEGRADED:
305 sprintf(statebuf, "UNKNOWN(0x%02x)", state);
310 ips_diskdev_init(ips_softc_t *sc)
314 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
315 if (sc->drives[i].state == IPS_LD_FREE)
317 device_printf(sc->dev,
318 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
319 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
320 ips_diskdev_statename(sc->drives[i].state));
321 if (sc->drives[i].state == IPS_LD_OKAY ||
322 sc->drives[i].state == IPS_LD_DEGRADED) {
323 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
324 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
327 if (bus_generic_attach(sc->dev))
328 device_printf(sc->dev, "Attaching bus failed\n");
333 ips_diskdev_free(ips_softc_t *sc)
338 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
339 if (sc->diskdev[i] != NULL) {
340 error = device_delete_child(sc->dev, sc->diskdev[i]);
345 bus_generic_detach(sc->dev);
350 * ips_timeout is periodically called to make sure no commands sent
351 * to the card have become stuck. If it finds a stuck command, it
352 * sets a flag so the driver won't start any more commands and then
353 * is periodically called to see if all outstanding commands have
354 * either finished or timed out. Once timed out, an attempt to
355 * reinitialize the card is made. If that fails, the driver gives
356 * up and declares the card dead.
359 ips_timeout(void *arg)
361 ips_command_t *command;
362 ips_softc_t *sc = arg;
365 command = &sc->commandarray[0];
367 for (i = 0; i < sc->max_cmds; i++) {
368 if (!command[i].timeout)
370 command[i].timeout--;
371 if (command[i].timeout == 0) {
372 if (!(sc->state & IPS_TIMEOUT)) {
373 sc->state |= IPS_TIMEOUT;
374 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
376 command[i].status.value = IPS_ERROR_STATUS;
377 command[i].callback(&command[i]);
378 /* hmm, this should be enough cleanup */
382 if (!state && (sc->state & IPS_TIMEOUT)) {
383 if (sc->ips_adapter_reinit(sc, 1)) {
384 device_printf(sc->dev, "AIEE! adapter reset failed, "
385 "giving up and going home! Have a nice day.\n");
386 sc->state |= IPS_OFFLINE;
387 sc->state &= ~IPS_TIMEOUT;
389 * Grr, I hate this solution. I run waiting commands
390 * one at a time and error them out just before they
391 * would go to the card. This sucks.
394 sc->state &= ~IPS_TIMEOUT;
395 ips_run_waiting_command(sc);
397 if (sc->state != IPS_OFFLINE)
398 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
402 /* check card and initialize it */
404 ips_adapter_init(ips_softc_t *sc)
409 DEVICE_PRINTF(1, sc->dev, "initializing\n");
410 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
413 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
414 /* highaddr */ BUS_SPACE_MAXADDR,
416 /* filterarg */ NULL,
417 /* maxsize */ IPS_COMMAND_LEN +
420 /* maxsegsize*/ IPS_COMMAND_LEN +
423 &sc->command_dmatag) != 0) {
424 device_printf(sc->dev, "can't alloc command dma tag\n");
427 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
430 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
431 /* highaddr */ BUS_SPACE_MAXADDR,
433 /* filterarg */ NULL,
434 /* maxsize */ IPS_MAX_IOBUF_SIZE,
435 /* numsegs */ IPS_MAX_SG_ELEMENTS,
436 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
438 &sc->sg_dmatag) != 0) {
439 device_printf(sc->dev, "can't alloc SG dma tag\n");
443 * create one command buffer until we know how many commands this card
447 ips_cmdqueue_init(sc);
448 callout_init(&sc->timer);
449 if (sc->ips_adapter_reinit(sc, 0))
451 /* initialize ffdc values */
452 microtime(&sc->ffdc_resettime);
453 sc->ffdc_resetcount = 1;
454 if ((i = ips_ffdc_reset(sc)) != 0) {
455 device_printf(sc->dev,
456 "failed to send ffdc reset to device (%d)\n", i);
459 if ((i = ips_get_adapter_info(sc)) != 0) {
460 device_printf(sc->dev, "failed to get adapter configuration "
461 "data from device (%d)\n", i);
464 /* no error check as failure doesn't matter */
465 ips_update_nvram(sc);
466 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
467 device_printf(sc->dev, "adapter type: %s\n",
468 ips_adapter_name[sc->adapter_type]);
470 if ((i = ips_get_drive_info(sc)) != 0) {
471 device_printf(sc->dev, "failed to get drive "
472 "configuration data from device (%d)\n", i);
475 ips_cmdqueue_free(sc);
476 if (sc->adapter_info.max_concurrent_cmds)
477 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
480 if (ips_cmdqueue_init(sc)) {
481 device_printf(sc->dev,
482 "failed to initialize command buffers\n");
485 cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
486 dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
487 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
488 "ips%d", device_get_unit(sc->dev));
490 ips_diskdev_init(sc);
491 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
494 ips_adapter_free(sc);
499 * see if we should reinitialize the card and wait for it to timeout
500 * or complete initialization
503 ips_morpheus_reinit(ips_softc_t *sc, int force)
508 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
509 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
510 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
511 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
514 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
515 ips_read_4(sc, MORPHEUS_REG_OIMR);
516 device_printf(sc->dev,
517 "resetting adapter, this may take up to 5 minutes\n");
518 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
520 pci_read_config(sc->dev, 0, 4);
521 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
522 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
524 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
525 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
527 if (tmp & MORPHEUS_BIT_POST1)
528 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
530 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
531 device_printf(sc->dev,
532 "Adapter error during initialization.\n");
535 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
537 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
538 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
540 if (tmp & MORPHEUS_BIT_POST2)
541 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
543 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
544 device_printf(sc->dev, "adapter failed config check\n");
547 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
548 if (force && ips_clear_adapter(sc)) {
549 device_printf(sc->dev, "adapter clear failed\n");
555 /* clean up so we can unload the driver. */
557 ips_adapter_free(ips_softc_t *sc)
561 if (sc->state & IPS_DEV_OPEN)
563 if ((error = ips_diskdev_free(sc)))
565 if (ips_cmdqueue_free(sc)) {
566 device_printf(sc->dev,
567 "trying to exit when command queue is not empty!\n");
570 DEVICE_PRINTF(1, sc->dev, "free\n");
572 callout_stop(&sc->timer);
575 bus_dma_tag_destroy(sc->sg_dmatag);
576 if (sc->command_dmatag)
577 bus_dma_tag_destroy(sc->command_dmatag);
578 cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
583 ips_morpheus_intr(void *void_sc)
585 ips_softc_t *sc = (ips_softc_t *)void_sc;
586 u_int32_t oisr, iisr;
587 ips_cmd_status_t status;
588 ips_command_t *command;
591 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
592 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
593 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
594 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
595 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
598 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
600 cmdnumber = status.fields.command_id;
601 command = &sc->commandarray[cmdnumber];
602 command->status.value = status.value;
603 command->timeout = 0;
604 command->callback(command);
605 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
611 ips_issue_morpheus_cmd(ips_command_t *command)
614 /* hmmm, is there a cleaner way to do this? */
615 if (command->sc->state & IPS_OFFLINE) {
617 command->status.value = IPS_ERROR_STATUS;
618 command->callback(command);
621 command->timeout = 10;
622 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
627 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
628 int segnum, int error)
630 ips_copper_queue_t *queue = queueptr;
634 queue->base_phys_addr = segments[0].ds_addr;
638 ips_copperhead_queue_init(ips_softc_t *sc)
640 bus_dma_tag_t dmatag;
644 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
647 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
648 /* highaddr */ BUS_SPACE_MAXADDR,
650 /* filterarg */ NULL,
651 /* maxsize */ sizeof(ips_copper_queue_t),
653 /* maxsegsize*/ sizeof(ips_copper_queue_t),
656 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
660 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
661 BUS_DMA_NOWAIT, &dmamap)) {
665 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
666 sc->copper_queue->dmatag = dmatag;
667 sc->copper_queue->dmamap = dmamap;
668 sc->copper_queue->nextstatus = 1;
669 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
670 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
671 sc->copper_queue, BUS_DMA_NOWAIT);
672 if (sc->copper_queue->base_phys_addr == 0) {
676 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
677 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
678 IPS_MAX_CMD_NUM * 4);
679 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
680 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
683 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
684 bus_dma_tag_destroy(dmatag);
689 * see if we should reinitialize the card and wait for it to timeout or
690 * complete initialization FIXME
693 ips_copperhead_reinit(ips_softc_t *sc, int force)
695 u_int32_t postcode = 0, configstatus = 0;
698 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
699 ips_write_1(sc, COPPER_REG_SCPR, 0);
700 device_printf(sc->dev,
701 "reinitializing adapter, this could take several minutes.\n");
702 for (j = 0; j < 2; j++) {
704 for (i = 0; i < 45; i++) {
705 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
706 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
707 ips_write_1(sc, COPPER_REG_HISR,
716 for (j = 0; j < 2; j++) {
718 for (i = 0; i < 240; i++) {
719 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
720 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
721 ips_write_1(sc, COPPER_REG_HISR,
730 for (i = 0; i < 240; i++) {
731 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
738 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
739 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
740 ips_copperhead_queue_init(sc);
741 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
742 i = ips_read_1(sc, COPPER_REG_SCPR);
743 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
744 if (configstatus == 0) {
745 device_printf(sc->dev, "adapter initialization failed\n");
748 if (force && ips_clear_adapter(sc)) {
749 device_printf(sc->dev, "adapter clear failed\n");
756 ips_copperhead_cmd_status(ips_softc_t *sc)
761 statnum = sc->copper_queue->nextstatus++;
762 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
763 sc->copper_queue->nextstatus = 0;
765 value = sc->copper_queue->status[statnum];
766 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
773 ips_copperhead_intr(void *void_sc)
775 ips_softc_t *sc = (ips_softc_t *)void_sc;
776 ips_cmd_status_t status;
779 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
780 status.value = ips_copperhead_cmd_status(sc);
781 cmdnumber = status.fields.command_id;
782 sc->commandarray[cmdnumber].status.value = status.value;
783 sc->commandarray[cmdnumber].timeout = 0;
784 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
785 PRINTF(9, "ips: got command %d\n", cmdnumber);
791 ips_issue_copperhead_cmd(ips_command_t *command)
796 /* hmmm, is there a cleaner way to do this? */
797 if (command->sc->state & IPS_OFFLINE) {
799 command->status.value = IPS_ERROR_STATUS;
800 command->callback(command);
803 command->timeout = 10;
804 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
807 printf("sem bit still set, can't send a command\n");
811 DELAY(500); /* need to do a delay here */
813 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
814 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);