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.6 2003/11/27 08:37:36 mbr $
28 * $DragonFly: src/sys/dev/raid/ips/ips.c,v 1.6 2004/07/09 16:15:27 dillon Exp $
31 #include <sys/cdefs.h>
33 #include <dev/raid/ips/ips.h>
36 #include <machine/clock.h>
38 static d_open_t ips_open;
39 static d_close_t ips_close;
40 static d_ioctl_t ips_ioctl;
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)
121 if (sc->used_commands == 0) {
122 for (i = 0; i < sc->max_cmds; i++) {
123 if (sc->commandarray[i].command_phys_addr == 0)
125 bus_dmamap_unload(sc->command_dmatag,
126 sc->commandarray[i].command_dmamap);
127 bus_dmamem_free(sc->command_dmatag,
128 sc->commandarray[i].command_buffer,
129 sc->commandarray[i].command_dmamap);
132 sc->state |= IPS_OFFLINE;
138 /* places all ips command structs on the free command queue. No locking as if someone else tries
139 * to access this during init, we have bigger problems */
140 static __inline__ int
141 ips_cmdqueue_init(ips_softc_t *sc)
144 ips_command_t *command;
146 SLIST_INIT(&sc->free_cmd_list);
147 STAILQ_INIT(&sc->cmd_wait_list);
148 for (i = 0; i < sc->max_cmds; i++) {
149 sc->commandarray[i].id = i;
150 sc->commandarray[i].sc = sc;
151 SLIST_INSERT_HEAD(&sc->free_cmd_list, &sc->commandarray[i],
154 for (i = 0; i < sc->max_cmds; i++) {
155 command = &sc->commandarray[i];
156 if (bus_dmamem_alloc(sc->command_dmatag,
157 &command->command_buffer, BUS_DMA_NOWAIT,
158 &command->command_dmamap))
160 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
161 command->command_buffer, IPS_COMMAND_LEN, ips_cmd_dmaload,
162 command, BUS_DMA_NOWAIT);
163 if (command->command_phys_addr == 0) {
164 bus_dmamem_free(sc->command_dmatag,
165 command->command_buffer, command->command_dmamap);
169 sc->state &= ~IPS_OFFLINE;
172 ips_cmdqueue_free(sc);
177 ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *),
181 ips_command_t *command;
182 ips_wait_list_t *waiter;
184 waiter = malloc(sizeof(ips_wait_list_t), M_DEVBUF, M_INTWAIT);
186 if (sc->state & IPS_OFFLINE) {
188 free(waiter, M_DEVBUF);
191 command = SLIST_FIRST(&sc->free_cmd_list);
192 if (command && !(sc->state & IPS_TIMEOUT)) {
193 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
196 clear_ips_command(command);
197 bzero(command->command_buffer, IPS_COMMAND_LEN);
198 free(waiter, M_DEVBUF);
200 return callback(command);
202 DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
203 waiter->callback = callback;
205 STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
211 ips_run_waiting_command(ips_softc_t *sc)
213 ips_wait_list_t *waiter;
214 ips_command_t *command;
215 int (*callback)(ips_command_t*);
219 waiter = STAILQ_FIRST(&sc->cmd_wait_list);
220 command = SLIST_FIRST(&sc->free_cmd_list);
221 if (waiter == NULL || command == NULL) {
225 DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
226 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
227 STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
230 clear_ips_command(command);
231 bzero(command->command_buffer, IPS_COMMAND_LEN);
232 command->arg = waiter->data;
233 callback = waiter->callback;
234 free(waiter, M_DEVBUF);
240 * returns a free command struct if one is available.
241 * It also blanks out anything that may be a wild pointer/value.
242 * Also, command buffers are not freed. They are
243 * small so they are saved and kept dmamapped and loaded.
246 ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data,
249 ips_command_t *command;
253 if (sc->state & IPS_OFFLINE) {
257 command = SLIST_FIRST(&sc->free_cmd_list);
258 if (!command || (sc->state & IPS_TIMEOUT)) {
260 if (flags & IPS_NOWAIT_FLAG)
262 return ips_add_waiting_command(sc, callback, data);
264 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
267 clear_ips_command(command);
268 bzero(command->command_buffer, IPS_COMMAND_LEN);
270 return callback(command);
273 /* adds a command back to the free command queue */
275 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
280 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
283 if (!(sc->state & IPS_TIMEOUT))
284 ips_run_waiting_command(sc);
287 ips_diskdev_statename(u_int8_t state)
289 static char statebuf[20];
298 case IPS_LD_DEGRADED:
311 sprintf(statebuf, "UNKNOWN(0x%02x)", state);
316 ips_diskdev_init(ips_softc_t *sc)
320 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
321 if (sc->drives[i].state == IPS_LD_FREE)
323 device_printf(sc->dev,
324 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
325 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
326 ips_diskdev_statename(sc->drives[i].state));
327 if (sc->drives[i].state == IPS_LD_OKAY ||
328 sc->drives[i].state == IPS_LD_DEGRADED) {
329 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
330 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
333 if (bus_generic_attach(sc->dev))
334 device_printf(sc->dev, "Attaching bus failed\n");
339 ips_diskdev_free(ips_softc_t *sc)
344 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
345 if (sc->diskdev[i] != NULL) {
346 error = device_delete_child(sc->dev, sc->diskdev[i]);
351 bus_generic_detach(sc->dev);
356 * ips_timeout is periodically called to make sure no commands sent
357 * to the card have become stuck. If it finds a stuck command, it
358 * sets a flag so the driver won't start any more commands and then
359 * is periodically called to see if all outstanding commands have
360 * either finished or timed out. Once timed out, an attempt to
361 * reinitialize the card is made. If that fails, the driver gives
362 * up and declares the card dead.
365 ips_timeout(void *arg)
367 ips_command_t *command;
368 ips_softc_t *sc = arg;
372 command = &sc->commandarray[0];
374 for (i = 0; i < sc->max_cmds; i++) {
375 if (!command[i].timeout)
377 command[i].timeout--;
378 if (command[i].timeout == 0) {
379 if (!(sc->state & IPS_TIMEOUT)) {
380 sc->state |= IPS_TIMEOUT;
381 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
383 command[i].status.value = IPS_ERROR_STATUS;
384 command[i].callback(&command[i]);
385 /* hmm, this should be enough cleanup */
389 if (!state && (sc->state & IPS_TIMEOUT)) {
390 if (sc->ips_adapter_reinit(sc, 1)) {
391 device_printf(sc->dev, "AIEE! adapter reset failed, "
392 "giving up and going home! Have a nice day.\n");
393 sc->state |= IPS_OFFLINE;
394 sc->state &= ~IPS_TIMEOUT;
396 * Grr, I hate this solution. I run waiting commands
397 * one at a time and error them out just before they
398 * would go to the card. This sucks.
401 sc->state &= ~IPS_TIMEOUT;
402 ips_run_waiting_command(sc);
404 if (sc->state != IPS_OFFLINE)
405 sc->timer = timeout(ips_timeout, sc, 10 * hz);
409 /* check card and initialize it */
411 ips_adapter_init(ips_softc_t *sc)
416 DEVICE_PRINTF(1, sc->dev, "initializing\n");
417 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
420 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
421 /* highaddr */ BUS_SPACE_MAXADDR,
423 /* filterarg */ NULL,
424 /* maxsize */ IPS_COMMAND_LEN +
427 /* maxsegsize*/ IPS_COMMAND_LEN +
430 &sc->command_dmatag) != 0) {
431 device_printf(sc->dev, "can't alloc command dma tag\n");
434 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
437 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
438 /* highaddr */ BUS_SPACE_MAXADDR,
440 /* filterarg */ NULL,
441 /* maxsize */ IPS_MAX_IOBUF_SIZE,
442 /* numsegs */ IPS_MAX_SG_ELEMENTS,
443 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
445 &sc->sg_dmatag) != 0) {
446 device_printf(sc->dev, "can't alloc SG dma tag\n");
450 * create one command buffer until we know how many commands this card
454 ips_cmdqueue_init(sc);
455 callout_handle_init(&sc->timer);
456 if (sc->ips_adapter_reinit(sc, 0))
459 /* initialize ffdc values */
460 microtime(&sc->ffdc_resettime);
461 sc->ffdc_resetcount = 1;
462 if ((i = ips_ffdc_reset(sc)) != 0) {
463 device_printf(sc->dev,
464 "failed to send ffdc reset to device (%d)\n", i);
467 if ((i = ips_get_adapter_info(sc)) != 0) {
468 device_printf(sc->dev, "failed to get adapter configuration "
469 "data from device (%d)\n", i);
472 /* no error check as failure doesn't matter */
473 ips_update_nvram(sc);
474 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
475 device_printf(sc->dev, "adapter type: %s\n",
476 ips_adapter_name[sc->adapter_type]);
478 if ((i = ips_get_drive_info(sc)) != 0) {
479 device_printf(sc->dev, "failed to get drive "
480 "configuration data from device (%d)\n", i);
483 ips_cmdqueue_free(sc);
484 if (sc->adapter_info.max_concurrent_cmds)
485 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
488 if (ips_cmdqueue_init(sc)) {
489 device_printf(sc->dev,
490 "failed to initialize command buffers\n");
493 cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
494 dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
495 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
496 "ips%d", device_get_unit(sc->dev));
498 ips_diskdev_init(sc);
499 sc->timer = timeout(ips_timeout, sc, 10*hz);
502 ips_adapter_free(sc);
507 * see if we should reinitialize the card and wait for it to timeout
508 * or complete initialization
511 ips_morpheus_reinit(ips_softc_t *sc, int force)
516 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
517 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
518 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
519 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
522 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
523 ips_read_4(sc, MORPHEUS_REG_OIMR);
524 device_printf(sc->dev,
525 "resetting adapter, this may take up to 5 minutes\n");
526 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
528 pci_read_config(sc->dev, 0, 4);
529 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
530 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
532 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
533 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
535 if (tmp & MORPHEUS_BIT_POST1)
536 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
538 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
539 device_printf(sc->dev,
540 "Adapter error during initialization.\n");
543 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
545 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
546 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
548 if (tmp & MORPHEUS_BIT_POST2)
549 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
551 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
552 device_printf(sc->dev, "adapter failed config check\n");
555 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
556 if (force && ips_clear_adapter(sc)) {
557 device_printf(sc->dev, "adapter clear failed\n");
563 /* clean up so we can unload the driver. */
565 ips_adapter_free(ips_softc_t *sc)
569 if (sc->state & IPS_DEV_OPEN)
571 if ((error = ips_diskdev_free(sc)))
573 if (ips_cmdqueue_free(sc)) {
574 device_printf(sc->dev,
575 "trying to exit when command queue is not empty!\n");
578 DEVICE_PRINTF(1, sc->dev, "free\n");
580 untimeout(ips_timeout, sc, sc->timer);
584 bus_dma_tag_destroy(sc->sg_dmatag);
585 if (sc->command_dmatag)
586 bus_dma_tag_destroy(sc->command_dmatag);
587 cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
592 ips_morpheus_intr(void *void_sc)
594 ips_softc_t *sc = (ips_softc_t *)void_sc;
595 u_int32_t oisr, iisr;
596 ips_cmd_status_t status;
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 sc->commandarray[cmdnumber].status.value = status.value;
610 sc->commandarray[cmdnumber].timeout = 0;
611 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
612 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
618 ips_issue_morpheus_cmd(ips_command_t *command)
623 /* hmmm, is there a cleaner way to do this? */
624 if (command->sc->state & IPS_OFFLINE) {
626 command->status.value = IPS_ERROR_STATUS;
627 command->callback(command);
630 command->timeout = 10;
631 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
636 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
637 int segnum, int error)
639 ips_copper_queue_t *queue = queueptr;
643 queue->base_phys_addr = segments[0].ds_addr;
647 ips_copperhead_queue_init(ips_softc_t *sc)
649 bus_dma_tag_t dmatag;
653 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
656 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
657 /* highaddr */ BUS_SPACE_MAXADDR,
659 /* filterarg */ NULL,
660 /* maxsize */ sizeof(ips_copper_queue_t),
662 /* maxsegsize*/ sizeof(ips_copper_queue_t),
665 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
669 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
670 BUS_DMA_NOWAIT, &dmamap)) {
674 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
675 sc->copper_queue->dmatag = dmatag;
676 sc->copper_queue->dmamap = dmamap;
677 sc->copper_queue->nextstatus = 1;
678 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
679 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
680 sc->copper_queue, BUS_DMA_NOWAIT);
681 if (sc->copper_queue->base_phys_addr == 0) {
685 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
686 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
687 IPS_MAX_CMD_NUM * 4);
688 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
689 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
692 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
693 bus_dma_tag_destroy(dmatag);
698 * see if we should reinitialize the card and wait for it to timeout or
699 * complete initialization FIXME
702 ips_copperhead_reinit(ips_softc_t *sc, int force)
704 u_int32_t postcode = 0, configstatus = 0;
707 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
708 ips_write_1(sc, COPPER_REG_SCPR, 0);
709 device_printf(sc->dev,
710 "reinitializing adapter, this could take several minutes.\n");
711 for (j = 0; j < 2; j++) {
713 for (i = 0; i < 45; i++) {
714 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
715 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
716 ips_write_1(sc, COPPER_REG_HISR,
725 for (j = 0; j < 2; j++) {
727 for (i = 0; i < 240; i++) {
728 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
729 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
730 ips_write_1(sc, COPPER_REG_HISR,
739 for (i = 0; i < 240; i++) {
740 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
747 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
748 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
749 ips_copperhead_queue_init(sc);
750 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
751 i = ips_read_1(sc, COPPER_REG_SCPR);
752 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
753 if (configstatus == 0) {
754 device_printf(sc->dev, "adapter initialization failed\n");
757 if (force && ips_clear_adapter(sc)) {
758 device_printf(sc->dev, "adapter clear failed\n");
765 ips_copperhead_cmd_status(ips_softc_t *sc)
771 statnum = sc->copper_queue->nextstatus++;
772 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
773 sc->copper_queue->nextstatus = 0;
775 value = sc->copper_queue->status[statnum];
776 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
783 ips_copperhead_intr(void *void_sc)
785 ips_softc_t *sc = (ips_softc_t *)void_sc;
786 ips_cmd_status_t status;
789 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
790 status.value = ips_copperhead_cmd_status(sc);
791 cmdnumber = status.fields.command_id;
792 sc->commandarray[cmdnumber].status.value = status.value;
793 sc->commandarray[cmdnumber].timeout = 0;
794 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
795 PRINTF(9, "ips: got command %d\n", cmdnumber);
801 ips_issue_copperhead_cmd(ips_command_t *command)
807 /* hmmm, is there a cleaner way to do this? */
808 if (command->sc->state & IPS_OFFLINE) {
810 command->status.value = IPS_ERROR_STATUS;
811 command->callback(command);
814 command->timeout = 10;
815 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
818 printf("sem bit still set, can't send a command\n");
822 DELAY(500); /* need to do a delay here */
824 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
825 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);