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.4 2004/05/19 22:52:47 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 *),
178 void *data, unsigned long flags)
181 ips_command_t *command;
182 ips_wait_list_t *waiter;
183 unsigned long memflags = 0;
185 if (IPS_NOWAIT_FLAG & flags)
187 waiter = malloc(sizeof(ips_wait_list_t), M_DEVBUF, memflags);
191 if (sc->state & IPS_OFFLINE) {
193 free(waiter, M_DEVBUF);
196 command = SLIST_FIRST(&sc->free_cmd_list);
197 if (command && !(sc->state & IPS_TIMEOUT)) {
198 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
201 clear_ips_command(command);
202 bzero(command->command_buffer, IPS_COMMAND_LEN);
203 free(waiter, M_DEVBUF);
205 return callback(command);
207 DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
208 waiter->callback = callback;
210 STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
216 ips_run_waiting_command(ips_softc_t *sc)
218 ips_wait_list_t *waiter;
219 ips_command_t *command;
220 int (*callback)(ips_command_t*);
224 waiter = STAILQ_FIRST(&sc->cmd_wait_list);
225 command = SLIST_FIRST(&sc->free_cmd_list);
226 if (waiter == NULL || command == NULL) {
230 DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
231 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
232 STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
235 clear_ips_command(command);
236 bzero(command->command_buffer, IPS_COMMAND_LEN);
237 command->arg = waiter->data;
238 callback = waiter->callback;
239 free(waiter, M_DEVBUF);
245 * returns a free command struct if one is available.
246 * It also blanks out anything that may be a wild pointer/value.
247 * Also, command buffers are not freed. They are
248 * small so they are saved and kept dmamapped and loaded.
251 ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data,
254 ips_command_t *command;
258 if (sc->state & IPS_OFFLINE) {
262 command = SLIST_FIRST(&sc->free_cmd_list);
263 if (!command || (sc->state & IPS_TIMEOUT)) {
265 if (flags & IPS_NOWAIT_FLAG)
267 return ips_add_waiting_command(sc, callback, data, flags);
269 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
272 clear_ips_command(command);
273 bzero(command->command_buffer, IPS_COMMAND_LEN);
275 return callback(command);
278 /* adds a command back to the free command queue */
280 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
285 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
288 if (!(sc->state & IPS_TIMEOUT))
289 ips_run_waiting_command(sc);
292 ips_diskdev_statename(u_int8_t state)
294 static char statebuf[20];
303 case IPS_LD_DEGRADED:
316 sprintf(statebuf, "UNKNOWN(0x%02x)", state);
321 ips_diskdev_init(ips_softc_t *sc)
325 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
326 if (sc->drives[i].state == IPS_LD_FREE)
328 device_printf(sc->dev,
329 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
330 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
331 ips_diskdev_statename(sc->drives[i].state));
332 if (sc->drives[i].state == IPS_LD_OKAY ||
333 sc->drives[i].state == IPS_LD_DEGRADED) {
334 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
335 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
338 if (bus_generic_attach(sc->dev))
339 device_printf(sc->dev, "Attaching bus failed\n");
344 ips_diskdev_free(ips_softc_t *sc)
349 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
350 if (sc->diskdev[i] != NULL) {
351 error = device_delete_child(sc->dev, sc->diskdev[i]);
356 bus_generic_detach(sc->dev);
361 * ips_timeout is periodically called to make sure no commands sent
362 * to the card have become stuck. If it finds a stuck command, it
363 * sets a flag so the driver won't start any more commands and then
364 * is periodically called to see if all outstanding commands have
365 * either finished or timed out. Once timed out, an attempt to
366 * reinitialize the card is made. If that fails, the driver gives
367 * up and declares the card dead.
370 ips_timeout(void *arg)
372 ips_command_t *command;
373 ips_softc_t *sc = arg;
377 command = &sc->commandarray[0];
379 for (i = 0; i < sc->max_cmds; i++) {
380 if (!command[i].timeout)
382 command[i].timeout--;
383 if (command[i].timeout == 0) {
384 if (!(sc->state & IPS_TIMEOUT)) {
385 sc->state |= IPS_TIMEOUT;
386 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
388 command[i].status.value = IPS_ERROR_STATUS;
389 command[i].callback(&command[i]);
390 /* hmm, this should be enough cleanup */
394 if (!state && (sc->state & IPS_TIMEOUT)) {
395 if (sc->ips_adapter_reinit(sc, 1)) {
396 device_printf(sc->dev, "AIEE! adapter reset failed, "
397 "giving up and going home! Have a nice day.\n");
398 sc->state |= IPS_OFFLINE;
399 sc->state &= ~IPS_TIMEOUT;
401 * Grr, I hate this solution. I run waiting commands
402 * one at a time and error them out just before they
403 * would go to the card. This sucks.
406 sc->state &= ~IPS_TIMEOUT;
407 ips_run_waiting_command(sc);
409 if (sc->state != IPS_OFFLINE)
410 sc->timer = timeout(ips_timeout, sc, 10 * hz);
414 /* check card and initialize it */
416 ips_adapter_init(ips_softc_t *sc)
421 DEVICE_PRINTF(1, sc->dev, "initializing\n");
422 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
425 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
426 /* highaddr */ BUS_SPACE_MAXADDR,
428 /* filterarg */ NULL,
429 /* maxsize */ IPS_COMMAND_LEN +
432 /* maxsegsize*/ IPS_COMMAND_LEN +
435 &sc->command_dmatag) != 0) {
436 device_printf(sc->dev, "can't alloc command dma tag\n");
439 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
442 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
443 /* highaddr */ BUS_SPACE_MAXADDR,
445 /* filterarg */ NULL,
446 /* maxsize */ IPS_MAX_IOBUF_SIZE,
447 /* numsegs */ IPS_MAX_SG_ELEMENTS,
448 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
450 &sc->sg_dmatag) != 0) {
451 device_printf(sc->dev, "can't alloc SG dma tag\n");
455 * create one command buffer until we know how many commands this card
459 ips_cmdqueue_init(sc);
460 callout_handle_init(&sc->timer);
461 if (sc->ips_adapter_reinit(sc, 0))
464 /* initialize ffdc values */
465 microtime(&sc->ffdc_resettime);
466 sc->ffdc_resetcount = 1;
467 if ((i = ips_ffdc_reset(sc)) != 0) {
468 device_printf(sc->dev,
469 "failed to send ffdc reset to device (%d)\n", i);
472 if ((i = ips_get_adapter_info(sc)) != 0) {
473 device_printf(sc->dev, "failed to get adapter configuration "
474 "data from device (%d)\n", i);
477 /* no error check as failure doesn't matter */
478 ips_update_nvram(sc);
479 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
480 device_printf(sc->dev, "adapter type: %s\n",
481 ips_adapter_name[sc->adapter_type]);
483 if ((i = ips_get_drive_info(sc)) != 0) {
484 device_printf(sc->dev, "failed to get drive "
485 "configuration data from device (%d)\n", i);
488 ips_cmdqueue_free(sc);
489 if (sc->adapter_info.max_concurrent_cmds)
490 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
493 if (ips_cmdqueue_init(sc)) {
494 device_printf(sc->dev,
495 "failed to initialize command buffers\n");
498 cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
499 dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
500 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
501 "ips%d", device_get_unit(sc->dev));
503 ips_diskdev_init(sc);
504 sc->timer = timeout(ips_timeout, sc, 10*hz);
507 ips_adapter_free(sc);
512 * see if we should reinitialize the card and wait for it to timeout
513 * or complete initialization
516 ips_morpheus_reinit(ips_softc_t *sc, int force)
521 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
522 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
523 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
524 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
527 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
528 ips_read_4(sc, MORPHEUS_REG_OIMR);
529 device_printf(sc->dev,
530 "resetting adapter, this may take up to 5 minutes\n");
531 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
533 pci_read_config(sc->dev, 0, 4);
534 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
535 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
537 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
538 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
540 if (tmp & MORPHEUS_BIT_POST1)
541 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
543 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
544 device_printf(sc->dev,
545 "Adapter error during initialization.\n");
548 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
550 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
551 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
553 if (tmp & MORPHEUS_BIT_POST2)
554 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
556 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
557 device_printf(sc->dev, "adapter failed config check\n");
560 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
561 if (force && ips_clear_adapter(sc)) {
562 device_printf(sc->dev, "adapter clear failed\n");
568 /* clean up so we can unload the driver. */
570 ips_adapter_free(ips_softc_t *sc)
574 if (sc->state & IPS_DEV_OPEN)
576 if ((error = ips_diskdev_free(sc)))
578 if (ips_cmdqueue_free(sc)) {
579 device_printf(sc->dev,
580 "trying to exit when command queue is not empty!\n");
583 DEVICE_PRINTF(1, sc->dev, "free\n");
585 untimeout(ips_timeout, sc, sc->timer);
589 bus_dma_tag_destroy(sc->sg_dmatag);
590 if (sc->command_dmatag)
591 bus_dma_tag_destroy(sc->command_dmatag);
592 cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
597 ips_morpheus_intr(void *void_sc)
599 ips_softc_t *sc = (ips_softc_t *)void_sc;
600 u_int32_t oisr, iisr;
601 ips_cmd_status_t status;
604 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
605 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
606 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
607 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
608 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
611 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
613 cmdnumber = status.fields.command_id;
614 sc->commandarray[cmdnumber].status.value = status.value;
615 sc->commandarray[cmdnumber].timeout = 0;
616 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
617 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
623 ips_issue_morpheus_cmd(ips_command_t *command)
628 /* hmmm, is there a cleaner way to do this? */
629 if (command->sc->state & IPS_OFFLINE) {
631 command->status.value = IPS_ERROR_STATUS;
632 command->callback(command);
635 command->timeout = 10;
636 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
641 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
642 int segnum, int error)
644 ips_copper_queue_t *queue = queueptr;
648 queue->base_phys_addr = segments[0].ds_addr;
652 ips_copperhead_queue_init(ips_softc_t *sc)
654 bus_dma_tag_t dmatag;
658 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
661 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
662 /* highaddr */ BUS_SPACE_MAXADDR,
664 /* filterarg */ NULL,
665 /* maxsize */ sizeof(ips_copper_queue_t),
667 /* maxsegsize*/ sizeof(ips_copper_queue_t),
670 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
674 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
675 BUS_DMA_NOWAIT, &dmamap)) {
679 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
680 sc->copper_queue->dmatag = dmatag;
681 sc->copper_queue->dmamap = dmamap;
682 sc->copper_queue->nextstatus = 1;
683 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
684 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
685 sc->copper_queue, BUS_DMA_NOWAIT);
686 if (sc->copper_queue->base_phys_addr == 0) {
690 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
691 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
692 IPS_MAX_CMD_NUM * 4);
693 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
694 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
697 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
698 bus_dma_tag_destroy(dmatag);
703 * see if we should reinitialize the card and wait for it to timeout or
704 * complete initialization FIXME
707 ips_copperhead_reinit(ips_softc_t *sc, int force)
709 u_int32_t postcode = 0, configstatus = 0;
712 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
713 ips_write_1(sc, COPPER_REG_SCPR, 0);
714 device_printf(sc->dev,
715 "reinitializing adapter, this could take several minutes.\n");
716 for (j = 0; j < 2; j++) {
718 for (i = 0; i < 45; i++) {
719 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
720 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
721 ips_write_1(sc, COPPER_REG_HISR,
730 for (j = 0; j < 2; j++) {
732 for (i = 0; i < 240; i++) {
733 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
734 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
735 ips_write_1(sc, COPPER_REG_HISR,
744 for (i = 0; i < 240; i++) {
745 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
752 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
753 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
754 ips_copperhead_queue_init(sc);
755 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
756 i = ips_read_1(sc, COPPER_REG_SCPR);
757 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
758 if (configstatus == 0) {
759 device_printf(sc->dev, "adapter initialization failed\n");
762 if (force && ips_clear_adapter(sc)) {
763 device_printf(sc->dev, "adapter clear failed\n");
770 ips_copperhead_cmd_status(ips_softc_t *sc)
776 statnum = sc->copper_queue->nextstatus++;
777 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
778 sc->copper_queue->nextstatus = 0;
780 value = sc->copper_queue->status[statnum];
781 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
788 ips_copperhead_intr(void *void_sc)
790 ips_softc_t *sc = (ips_softc_t *)void_sc;
791 ips_cmd_status_t status;
794 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
795 status.value = ips_copperhead_cmd_status(sc);
796 cmdnumber = status.fields.command_id;
797 sc->commandarray[cmdnumber].status.value = status.value;
798 sc->commandarray[cmdnumber].timeout = 0;
799 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
800 PRINTF(9, "ips: got command %d\n", cmdnumber);
806 ips_issue_copperhead_cmd(ips_command_t *command)
812 /* hmmm, is there a cleaner way to do this? */
813 if (command->sc->state & IPS_OFFLINE) {
815 command->status.value = IPS_ERROR_STATUS;
816 command->callback(command);
819 command->timeout = 10;
820 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
823 printf("sem bit still set, can't send a command\n");
827 DELAY(500); /* need to do a delay here */
829 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
830 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);