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.12 2005/08/09 16:23:13 dillon 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? */
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);
132 if (command->data_dmamap != NULL)
133 bus_dmamap_destroy(command->data_dmatag,
134 command->data_dmamap);
137 sc->state |= IPS_OFFLINE;
139 sc->staticcmd = NULL;
140 free(sc->commandarray, M_IPSBUF);
146 * Places all ips command structs on the free command queue.
147 * The first slot is used exclusively for static commands
148 * No locking as if someone else tries to access this during init,
149 * we have bigger problems
152 ips_cmdqueue_init(ips_softc_t *sc)
155 ips_command_t *command;
157 sc->commandarray = malloc(sizeof(sc->commandarray[0]) * sc->max_cmds,
158 M_IPSBUF, M_INTWAIT | M_ZERO);
159 SLIST_INIT(&sc->free_cmd_list);
160 for (i = 0; i < sc->max_cmds; i++) {
161 command = &sc->commandarray[i];
164 if (bus_dmamem_alloc(sc->command_dmatag,
165 &command->command_buffer, BUS_DMA_NOWAIT,
166 &command->command_dmamap))
168 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
169 command->command_buffer, IPS_COMMAND_LEN, ips_cmd_dmaload,
170 command, BUS_DMA_NOWAIT);
171 if (command->command_phys_addr == 0) {
172 bus_dmamem_free(sc->command_dmatag,
173 command->command_buffer, command->command_dmamap);
178 sc->staticcmd = command;
180 command->data_dmatag = sc->sg_dmatag;
181 if (bus_dmamap_create(command->data_dmatag, 0,
182 &command->data_dmamap))
184 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
187 sc->state &= ~IPS_OFFLINE;
190 ips_cmdqueue_free(sc);
195 * returns a free command struct if one is available.
196 * It also blanks out anything that may be a wild pointer/value.
197 * Also, command buffers are not freed. They are
198 * small so they are saved and kept dmamapped and loaded.
201 ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags)
203 ips_command_t *command = NULL;
207 if (sc->state & IPS_OFFLINE) {
211 if ((flags & IPS_STATIC_FLAG) != 0) {
212 if (sc->state & IPS_STATIC_BUSY) {
216 command = sc->staticcmd;
217 sc->state |= IPS_STATIC_BUSY;
219 command = SLIST_FIRST(&sc->free_cmd_list);
220 if (!command || (sc->state & IPS_TIMEOUT)) {
224 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
232 bzero(&command->status, (char *)(command + 1) - (char *)(&command->status));
233 bzero(command->command_buffer, IPS_COMMAND_LEN);
238 /* adds a command back to the free command queue */
240 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
243 if (command == sc->staticcmd)
244 sc->state &= ~IPS_STATIC_BUSY;
246 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
253 ips_diskdev_statename(u_int8_t state)
255 static char statebuf[20];
264 case IPS_LD_DEGRADED:
277 sprintf(statebuf, "UNKNOWN(0x%02x)", state);
282 ips_diskdev_init(ips_softc_t *sc)
286 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
287 if (sc->drives[i].state == IPS_LD_FREE)
289 device_printf(sc->dev,
290 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
291 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
292 ips_diskdev_statename(sc->drives[i].state));
293 if (sc->drives[i].state == IPS_LD_OKAY ||
294 sc->drives[i].state == IPS_LD_DEGRADED) {
295 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
296 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
299 if (bus_generic_attach(sc->dev))
300 device_printf(sc->dev, "Attaching bus failed\n");
305 ips_diskdev_free(ips_softc_t *sc)
310 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
311 if (sc->diskdev[i] != NULL) {
312 error = device_delete_child(sc->dev, sc->diskdev[i]);
317 bus_generic_detach(sc->dev);
322 * ips_timeout is periodically called to make sure no commands sent
323 * to the card have become stuck. If it finds a stuck command, it
324 * sets a flag so the driver won't start any more commands and then
325 * is periodically called to see if all outstanding commands have
326 * either finished or timed out. Once timed out, an attempt to
327 * reinitialize the card is made. If that fails, the driver gives
328 * up and declares the card dead.
331 ips_timeout(void *arg)
333 ips_command_t *command;
334 ips_softc_t *sc = arg;
337 lwkt_exlock(&sc->queue_lock, __func__);
338 command = &sc->commandarray[0];
339 for (i = 0; i < sc->max_cmds; i++) {
340 if (!command[i].timeout)
342 command[i].timeout--;
343 if (command[i].timeout == 0) {
344 if (!(sc->state & IPS_TIMEOUT)) {
345 sc->state |= IPS_TIMEOUT;
346 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
348 command[i].status.value = IPS_ERROR_STATUS;
349 command[i].callback(&command[i]);
350 /* hmm, this should be enough cleanup */
354 if (!state && (sc->state & IPS_TIMEOUT)) {
355 if (sc->ips_adapter_reinit(sc, 1)) {
356 device_printf(sc->dev, "AIEE! adapter reset failed, "
357 "giving up and going home! Have a nice day.\n");
358 sc->state |= IPS_OFFLINE;
359 sc->state &= ~IPS_TIMEOUT;
361 * Grr, I hate this solution. I run waiting commands
362 * one at a time and error them out just before they
363 * would go to the card. This sucks.
366 sc->state &= ~IPS_TIMEOUT;
368 if (sc->state != IPS_OFFLINE)
369 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
370 lwkt_exunlock(&sc->queue_lock);
373 /* check card and initialize it */
375 ips_adapter_init(ips_softc_t *sc)
380 DEVICE_PRINTF(1, sc->dev, "initializing\n");
381 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
384 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
385 /* highaddr */ BUS_SPACE_MAXADDR,
387 /* filterarg */ NULL,
388 /* maxsize */ IPS_COMMAND_LEN +
391 /* maxsegsize*/ IPS_COMMAND_LEN +
394 &sc->command_dmatag) != 0) {
395 device_printf(sc->dev, "can't alloc command dma tag\n");
398 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
401 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
402 /* highaddr */ BUS_SPACE_MAXADDR,
404 /* filterarg */ NULL,
405 /* maxsize */ IPS_MAX_IOBUF_SIZE,
406 /* numsegs */ IPS_MAX_SG_ELEMENTS,
407 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
409 &sc->sg_dmatag) != 0) {
410 device_printf(sc->dev, "can't alloc SG dma tag\n");
414 * create one command buffer until we know how many commands this card
418 ips_cmdqueue_init(sc);
419 callout_init(&sc->timer);
420 if (sc->ips_adapter_reinit(sc, 0))
422 /* initialize ffdc values */
423 microtime(&sc->ffdc_resettime);
424 sc->ffdc_resetcount = 1;
425 if ((i = ips_ffdc_reset(sc)) != 0) {
426 device_printf(sc->dev,
427 "failed to send ffdc reset to device (%d)\n", i);
430 if ((i = ips_get_adapter_info(sc)) != 0) {
431 device_printf(sc->dev, "failed to get adapter configuration "
432 "data from device (%d)\n", i);
435 /* no error check as failure doesn't matter */
436 ips_update_nvram(sc);
437 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
438 device_printf(sc->dev, "adapter type: %s\n",
439 ips_adapter_name[sc->adapter_type]);
441 if ((i = ips_get_drive_info(sc)) != 0) {
442 device_printf(sc->dev, "failed to get drive "
443 "configuration data from device (%d)\n", i);
446 ips_cmdqueue_free(sc);
447 if (sc->adapter_info.max_concurrent_cmds)
448 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
451 if (ips_cmdqueue_init(sc)) {
452 device_printf(sc->dev,
453 "failed to initialize command buffers\n");
456 cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
457 dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
458 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
459 "ips%d", device_get_unit(sc->dev));
461 ips_diskdev_init(sc);
462 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
465 ips_adapter_free(sc);
470 * see if we should reinitialize the card and wait for it to timeout
471 * or complete initialization
474 ips_morpheus_reinit(ips_softc_t *sc, int force)
479 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
480 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
481 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
482 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
485 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
486 ips_read_4(sc, MORPHEUS_REG_OIMR);
487 device_printf(sc->dev,
488 "resetting adapter, this may take up to 5 minutes\n");
489 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
491 pci_read_config(sc->dev, 0, 4);
492 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
493 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
495 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
496 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
498 if (tmp & MORPHEUS_BIT_POST1)
499 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
501 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
502 device_printf(sc->dev,
503 "Adapter error during initialization.\n");
506 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
508 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
509 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
511 if (tmp & MORPHEUS_BIT_POST2)
512 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
514 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
515 device_printf(sc->dev, "adapter failed config check\n");
518 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
519 if (force && ips_clear_adapter(sc)) {
520 device_printf(sc->dev, "adapter clear failed\n");
526 /* clean up so we can unload the driver. */
528 ips_adapter_free(ips_softc_t *sc)
532 if (sc->state & IPS_DEV_OPEN)
534 if ((error = ips_diskdev_free(sc)))
536 if (ips_cmdqueue_free(sc)) {
537 device_printf(sc->dev,
538 "trying to exit when command queue is not empty!\n");
541 DEVICE_PRINTF(1, sc->dev, "free\n");
543 callout_stop(&sc->timer);
546 bus_dma_tag_destroy(sc->sg_dmatag);
547 if (sc->command_dmatag)
548 bus_dma_tag_destroy(sc->command_dmatag);
549 cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
554 ips_morpheus_check_intr(void *void_sc)
556 ips_softc_t *sc = (ips_softc_t *)void_sc;
557 u_int32_t oisr, iisr;
558 ips_cmd_status_t status;
559 ips_command_t *command;
563 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
564 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
565 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
566 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
567 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
570 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
572 cmdnumber = status.fields.command_id;
573 command = &sc->commandarray[cmdnumber];
574 command->status.value = status.value;
575 command->timeout = 0;
576 command->callback(command);
577 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
584 ips_morpheus_intr(void *void_sc)
586 ips_softc_t *sc = void_sc;
588 lwkt_exlock(&sc->queue_lock, __func__);
589 ips_morpheus_check_intr(sc);
590 lwkt_exunlock(&sc->queue_lock);
594 ips_issue_morpheus_cmd(ips_command_t *command)
597 /* hmmm, is there a cleaner way to do this? */
598 if (command->sc->state & IPS_OFFLINE) {
600 command->status.value = IPS_ERROR_STATUS;
601 command->callback(command);
604 command->timeout = 10;
605 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
610 ips_morpheus_poll(ips_command_t *command)
614 ts = time_second + command->timeout;
615 while (command->timeout != 0 &&
616 ips_morpheus_check_intr(command->sc) == 0 &&
622 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
623 int segnum, int error)
625 ips_copper_queue_t *queue = queueptr;
629 queue->base_phys_addr = segments[0].ds_addr;
633 ips_copperhead_queue_init(ips_softc_t *sc)
635 bus_dma_tag_t dmatag;
639 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
642 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
643 /* highaddr */ BUS_SPACE_MAXADDR,
645 /* filterarg */ NULL,
646 /* maxsize */ sizeof(ips_copper_queue_t),
648 /* maxsegsize*/ sizeof(ips_copper_queue_t),
651 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
655 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
656 BUS_DMA_NOWAIT, &dmamap)) {
660 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
661 sc->copper_queue->dmatag = dmatag;
662 sc->copper_queue->dmamap = dmamap;
663 sc->copper_queue->nextstatus = 1;
664 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
665 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
666 sc->copper_queue, BUS_DMA_NOWAIT);
667 if (sc->copper_queue->base_phys_addr == 0) {
671 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
672 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
673 IPS_MAX_CMD_NUM * 4);
674 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
675 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
678 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
679 bus_dma_tag_destroy(dmatag);
684 * see if we should reinitialize the card and wait for it to timeout or
685 * complete initialization FIXME
688 ips_copperhead_reinit(ips_softc_t *sc, int force)
690 u_int32_t postcode = 0, configstatus = 0;
693 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
694 ips_write_1(sc, COPPER_REG_SCPR, 0);
695 device_printf(sc->dev,
696 "reinitializing adapter, this could take several minutes.\n");
697 for (j = 0; j < 2; j++) {
699 for (i = 0; i < 45; i++) {
700 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
701 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
702 ips_write_1(sc, COPPER_REG_HISR,
711 for (j = 0; j < 2; j++) {
713 for (i = 0; i < 240; i++) {
714 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
715 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
716 ips_write_1(sc, COPPER_REG_HISR,
725 for (i = 0; i < 240; i++) {
726 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
733 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
734 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
735 ips_copperhead_queue_init(sc);
736 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
737 i = ips_read_1(sc, COPPER_REG_SCPR);
738 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
739 if (configstatus == 0) {
740 device_printf(sc->dev, "adapter initialization failed\n");
743 if (force && ips_clear_adapter(sc)) {
744 device_printf(sc->dev, "adapter clear failed\n");
751 ips_copperhead_cmd_status(ips_softc_t *sc)
756 statnum = sc->copper_queue->nextstatus++;
757 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
758 sc->copper_queue->nextstatus = 0;
760 value = sc->copper_queue->status[statnum];
761 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
768 ips_copperhead_intr(void *void_sc)
770 ips_softc_t *sc = (ips_softc_t *)void_sc;
771 ips_cmd_status_t status;
774 lwkt_exlock(&sc->queue_lock, __func__);
775 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
776 status.value = ips_copperhead_cmd_status(sc);
777 cmdnumber = status.fields.command_id;
778 sc->commandarray[cmdnumber].status.value = status.value;
779 sc->commandarray[cmdnumber].timeout = 0;
780 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
781 PRINTF(9, "ips: got command %d\n", cmdnumber);
783 lwkt_exunlock(&sc->queue_lock);
788 ips_issue_copperhead_cmd(ips_command_t *command)
793 /* hmmm, is there a cleaner way to do this? */
794 if (command->sc->state & IPS_OFFLINE) {
796 command->status.value = IPS_ERROR_STATUS;
797 command->callback(command);
800 command->timeout = 10;
801 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
804 printf("sem bit still set, can't send a command\n");
808 DELAY(500); /* need to do a delay here */
810 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
811 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
816 ips_copperhead_poll(ips_command_t *command)
818 printf("ips: cmd polling not implemented for copperhead devices\n");