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.19 2006/12/22 23:26:23 swildner Exp $
31 #include <dev/raid/ips/ips.h>
34 #include <sys/thread2.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 MALLOC_DEFINE(M_IPSBUF, "ipsbuf", "IPS driver buffer");
44 static struct dev_ops ips_ops = {
45 { "ips", IPS_CDEV_MAJOR, D_DISK },
51 static const char *ips_adapter_name[] = {
53 "ServeRAID (copperhead)",
54 "ServeRAID II (copperhead refresh)",
55 "ServeRAID onboard (copperhead)",
56 "ServeRAID onboard (copperhead)",
57 "ServeRAID 3H (clarinet)",
58 "ServeRAID 3L (clarinet lite)",
59 "ServeRAID 4H (trombone)",
60 "ServeRAID 4M (morpheus)",
61 "ServeRAID 4L (morpheus lite)",
62 "ServeRAID 4Mx (neo)",
63 "ServeRAID 4Lx (neo lite)",
64 "ServeRAID 5i II (sarasota)",
65 "ServeRAID 5i (sarasota)",
66 "ServeRAID 6M (marco)",
67 "ServeRAID 6i (sebring)",
75 ips_open(struct dev_open_args *ap)
77 cdev_t dev = ap->a_head.a_dev;
78 ips_softc_t *sc = dev->si_drv1;
80 sc->state |= IPS_DEV_OPEN;
85 ips_close(struct dev_close_args *ap)
87 cdev_t dev = ap->a_head.a_dev;
88 ips_softc_t *sc = dev->si_drv1;
90 sc->state &= ~IPS_DEV_OPEN;
95 ips_ioctl(struct dev_ioctl_args *ap)
99 sc = ap->a_head.a_dev->si_drv1;
100 return ips_ioctl_request(sc, ap->a_cmd, ap->a_data, ap->a_fflag);
104 ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments, int segnum,
107 ips_command_t *command = cmdptr;
109 PRINTF(10, "ips: in ips_cmd_dmaload\n");
111 command->command_phys_addr = segments[0].ds_addr;
115 /* is locking needed? what locking guarentees are there on removal? */
117 ips_cmdqueue_free(ips_softc_t *sc)
120 ips_command_t *command;
123 if (sc->used_commands == 0) {
124 for (i = 0; i < sc->max_cmds; i++) {
125 command = &sc->commandarray[i];
126 if (command->command_phys_addr == 0)
128 bus_dmamap_unload(sc->command_dmatag,
129 command->command_dmamap);
130 bus_dmamem_free(sc->command_dmatag,
131 command->command_buffer,
132 command->command_dmamap);
133 if (command->data_dmamap != NULL)
134 bus_dmamap_destroy(command->data_dmatag,
135 command->data_dmamap);
138 sc->state |= IPS_OFFLINE;
140 sc->staticcmd = NULL;
141 kfree(sc->commandarray, M_IPSBUF);
147 * Places all ips command structs on the free command queue.
148 * The first slot is used exclusively for static commands
149 * No locking as if someone else tries to access this during init,
150 * we have bigger problems
153 ips_cmdqueue_init(ips_softc_t *sc)
156 ips_command_t *command;
158 sc->commandarray = kmalloc(sizeof(sc->commandarray[0]) * sc->max_cmds,
159 M_IPSBUF, M_INTWAIT | M_ZERO);
160 SLIST_INIT(&sc->free_cmd_list);
161 for (i = 0; i < sc->max_cmds; i++) {
162 command = &sc->commandarray[i];
165 if (bus_dmamem_alloc(sc->command_dmatag,
166 &command->command_buffer, BUS_DMA_NOWAIT,
167 &command->command_dmamap))
169 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
170 command->command_buffer, IPS_COMMAND_LEN, ips_cmd_dmaload,
171 command, BUS_DMA_NOWAIT);
172 if (command->command_phys_addr == 0) {
173 bus_dmamem_free(sc->command_dmatag,
174 command->command_buffer, command->command_dmamap);
179 sc->staticcmd = command;
181 command->data_dmatag = sc->sg_dmatag;
182 if (bus_dmamap_create(command->data_dmatag, 0,
183 &command->data_dmamap))
185 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
188 sc->state &= ~IPS_OFFLINE;
191 ips_cmdqueue_free(sc);
196 * returns a free command struct if one is available.
197 * It also blanks out anything that may be a wild pointer/value.
198 * Also, command buffers are not freed. They are
199 * small so they are saved and kept dmamapped and loaded.
202 ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags)
204 ips_command_t *command = NULL;
208 if (sc->state & IPS_OFFLINE) {
212 if ((flags & IPS_STATIC_FLAG) != 0) {
213 if (sc->state & IPS_STATIC_BUSY) {
217 command = sc->staticcmd;
218 sc->state |= IPS_STATIC_BUSY;
220 command = SLIST_FIRST(&sc->free_cmd_list);
221 if (!command || (sc->state & IPS_TIMEOUT)) {
225 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
233 bzero(&command->status, (char *)(command + 1) - (char *)(&command->status));
234 bzero(command->command_buffer, IPS_COMMAND_LEN);
239 /* adds a command back to the free command queue */
241 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
244 if (command == sc->staticcmd)
245 sc->state &= ~IPS_STATIC_BUSY;
247 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
254 ips_diskdev_statename(u_int8_t state)
256 static char statebuf[20];
265 case IPS_LD_DEGRADED:
278 ksprintf(statebuf, "UNKNOWN(0x%02x)", state);
283 ips_diskdev_init(ips_softc_t *sc)
287 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
288 if (sc->drives[i].state == IPS_LD_FREE)
290 device_printf(sc->dev,
291 "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
292 sc->drives[i].raid_lvl, sc->drives[i].sector_count,
293 ips_diskdev_statename(sc->drives[i].state));
294 if (sc->drives[i].state == IPS_LD_OKAY ||
295 sc->drives[i].state == IPS_LD_DEGRADED) {
296 sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
297 device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
300 if (bus_generic_attach(sc->dev))
301 device_printf(sc->dev, "Attaching bus failed\n");
306 ips_diskdev_free(ips_softc_t *sc)
311 for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
312 if (sc->diskdev[i] != NULL) {
313 error = device_delete_child(sc->dev, sc->diskdev[i]);
318 bus_generic_detach(sc->dev);
323 * ips_timeout is periodically called to make sure no commands sent
324 * to the card have become stuck. If it finds a stuck command, it
325 * sets a flag so the driver won't start any more commands and then
326 * is periodically called to see if all outstanding commands have
327 * either finished or timed out. Once timed out, an attempt to
328 * reinitialize the card is made. If that fails, the driver gives
329 * up and declares the card dead.
332 ips_timeout(void *arg)
334 ips_command_t *command;
335 ips_softc_t *sc = arg;
338 lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
339 command = &sc->commandarray[0];
340 for (i = 0; i < sc->max_cmds; i++) {
341 if (!command[i].timeout)
343 command[i].timeout--;
344 if (command[i].timeout == 0) {
345 if (!(sc->state & IPS_TIMEOUT)) {
346 sc->state |= IPS_TIMEOUT;
347 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
349 command[i].status.value = IPS_ERROR_STATUS;
350 command[i].callback(&command[i]);
351 /* hmm, this should be enough cleanup */
355 if (!state && (sc->state & IPS_TIMEOUT)) {
356 if (sc->ips_adapter_reinit(sc, 1)) {
357 device_printf(sc->dev, "AIEE! adapter reset failed, "
358 "giving up and going home! Have a nice day.\n");
359 sc->state |= IPS_OFFLINE;
360 sc->state &= ~IPS_TIMEOUT;
362 * Grr, I hate this solution. I run waiting commands
363 * one at a time and error them out just before they
364 * would go to the card. This sucks.
367 sc->state &= ~IPS_TIMEOUT;
369 if (sc->state != IPS_OFFLINE)
370 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
371 lockmgr(&sc->queue_lock, LK_RELEASE);
374 /* check card and initialize it */
376 ips_adapter_init(ips_softc_t *sc)
381 DEVICE_PRINTF(1, sc->dev, "initializing\n");
382 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
385 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
386 /* highaddr */ BUS_SPACE_MAXADDR,
388 /* filterarg */ NULL,
389 /* maxsize */ IPS_COMMAND_LEN +
392 /* maxsegsize*/ IPS_COMMAND_LEN +
395 &sc->command_dmatag) != 0) {
396 device_printf(sc->dev, "can't alloc command dma tag\n");
399 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
402 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
403 /* highaddr */ BUS_SPACE_MAXADDR,
405 /* filterarg */ NULL,
406 /* maxsize */ IPS_MAX_IOBUF_SIZE,
407 /* numsegs */ IPS_MAX_SG_ELEMENTS,
408 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
410 &sc->sg_dmatag) != 0) {
411 device_printf(sc->dev, "can't alloc SG dma tag\n");
415 * create one command buffer until we know how many commands this card
419 ips_cmdqueue_init(sc);
420 callout_init(&sc->timer);
421 if (sc->ips_adapter_reinit(sc, 0))
423 /* initialize ffdc values */
424 microtime(&sc->ffdc_resettime);
425 sc->ffdc_resetcount = 1;
426 if ((i = ips_ffdc_reset(sc)) != 0) {
427 device_printf(sc->dev,
428 "failed to send ffdc reset to device (%d)\n", i);
431 if ((i = ips_get_adapter_info(sc)) != 0) {
432 device_printf(sc->dev, "failed to get adapter configuration "
433 "data from device (%d)\n", i);
436 /* no error check as failure doesn't matter */
437 ips_update_nvram(sc);
438 if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
439 device_printf(sc->dev, "adapter type: %s\n",
440 ips_adapter_name[sc->adapter_type]);
442 if ((i = ips_get_drive_info(sc)) != 0) {
443 device_printf(sc->dev, "failed to get drive "
444 "configuration data from device (%d)\n", i);
447 ips_cmdqueue_free(sc);
448 if (sc->adapter_info.max_concurrent_cmds)
449 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
452 if (ips_cmdqueue_init(sc)) {
453 device_printf(sc->dev,
454 "failed to initialize command buffers\n");
457 dev = make_dev(&ips_ops, device_get_unit(sc->dev),
458 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
459 "ips%d", device_get_unit(sc->dev));
461 udev_dict_set_cstr(dev, "subsystem", "raid");
462 udev_dict_set_cstr(dev, "disk-type", "raid");
463 ips_diskdev_init(sc);
464 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
467 ips_adapter_free(sc);
472 * see if we should reinitialize the card and wait for it to timeout
473 * or complete initialization
476 ips_morpheus_reinit(ips_softc_t *sc, int force)
481 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
482 if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
483 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
484 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
487 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
488 ips_read_4(sc, MORPHEUS_REG_OIMR);
489 device_printf(sc->dev,
490 "resetting adapter, this may take up to 5 minutes\n");
491 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
493 pci_read_config(sc->dev, 0, 4);
494 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
495 for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
497 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
498 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
500 if (tmp & MORPHEUS_BIT_POST1)
501 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
503 if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
504 device_printf(sc->dev,
505 "Adapter error during initialization.\n");
508 for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
510 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
511 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
513 if (tmp & MORPHEUS_BIT_POST2)
514 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
516 if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
517 device_printf(sc->dev, "adapter failed config check\n");
520 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
521 if (force && ips_clear_adapter(sc)) {
522 device_printf(sc->dev, "adapter clear failed\n");
528 /* clean up so we can unload the driver. */
530 ips_adapter_free(ips_softc_t *sc)
534 if (sc->state & IPS_DEV_OPEN)
536 if ((error = ips_diskdev_free(sc)))
538 if (ips_cmdqueue_free(sc)) {
539 device_printf(sc->dev,
540 "trying to exit when command queue is not empty!\n");
543 DEVICE_PRINTF(1, sc->dev, "free\n");
545 callout_stop(&sc->timer);
548 bus_dma_tag_destroy(sc->sg_dmatag);
549 if (sc->command_dmatag)
550 bus_dma_tag_destroy(sc->command_dmatag);
551 dev_ops_remove_minor(&ips_ops, device_get_unit(sc->dev));
556 ips_morpheus_check_intr(void *void_sc)
558 ips_softc_t *sc = (ips_softc_t *)void_sc;
559 u_int32_t oisr, iisr;
560 ips_cmd_status_t status;
561 ips_command_t *command;
565 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
566 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
567 PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
568 if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
569 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
572 while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
574 cmdnumber = status.fields.command_id;
575 command = &sc->commandarray[cmdnumber];
576 command->status.value = status.value;
577 command->timeout = 0;
578 command->callback(command);
579 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
586 ips_morpheus_intr(void *void_sc)
588 ips_softc_t *sc = void_sc;
590 lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
591 ips_morpheus_check_intr(sc);
592 lockmgr(&sc->queue_lock, LK_RELEASE);
596 ips_issue_morpheus_cmd(ips_command_t *command)
599 /* hmmm, is there a cleaner way to do this? */
600 if (command->sc->state & IPS_OFFLINE) {
602 command->status.value = IPS_ERROR_STATUS;
603 command->callback(command);
606 command->timeout = 10;
607 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
612 ips_morpheus_poll(ips_command_t *command)
616 ts = time_second + command->timeout;
617 while (command->timeout != 0 &&
618 ips_morpheus_check_intr(command->sc) == 0 &&
624 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
625 int segnum, int error)
627 ips_copper_queue_t *queue = queueptr;
631 queue->base_phys_addr = segments[0].ds_addr;
635 ips_copperhead_queue_init(ips_softc_t *sc)
637 bus_dma_tag_t dmatag;
641 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
644 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
645 /* highaddr */ BUS_SPACE_MAXADDR,
647 /* filterarg */ NULL,
648 /* maxsize */ sizeof(ips_copper_queue_t),
650 /* maxsegsize*/ sizeof(ips_copper_queue_t),
653 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
657 if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
658 BUS_DMA_NOWAIT, &dmamap)) {
662 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
663 sc->copper_queue->dmatag = dmatag;
664 sc->copper_queue->dmamap = dmamap;
665 sc->copper_queue->nextstatus = 1;
666 bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
667 IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
668 sc->copper_queue, BUS_DMA_NOWAIT);
669 if (sc->copper_queue->base_phys_addr == 0) {
673 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
674 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
675 IPS_MAX_CMD_NUM * 4);
676 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
677 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
680 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
681 bus_dma_tag_destroy(dmatag);
686 * see if we should reinitialize the card and wait for it to timeout or
687 * complete initialization FIXME
690 ips_copperhead_reinit(ips_softc_t *sc, int force)
692 u_int32_t postcode = 0, configstatus = 0;
695 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
696 ips_write_1(sc, COPPER_REG_SCPR, 0);
697 device_printf(sc->dev,
698 "reinitializing adapter, this could take several minutes.\n");
699 for (j = 0; j < 2; j++) {
701 for (i = 0; i < 45; i++) {
702 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
703 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
704 ips_write_1(sc, COPPER_REG_HISR,
713 for (j = 0; j < 2; j++) {
715 for (i = 0; i < 240; i++) {
716 if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
717 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
718 ips_write_1(sc, COPPER_REG_HISR,
727 for (i = 0; i < 240; i++) {
728 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
735 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
736 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
737 ips_copperhead_queue_init(sc);
738 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
739 i = ips_read_1(sc, COPPER_REG_SCPR);
740 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
741 if (configstatus == 0) {
742 device_printf(sc->dev, "adapter initialization failed\n");
745 if (force && ips_clear_adapter(sc)) {
746 device_printf(sc->dev, "adapter clear failed\n");
753 ips_copperhead_cmd_status(ips_softc_t *sc)
758 statnum = sc->copper_queue->nextstatus++;
759 if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
760 sc->copper_queue->nextstatus = 0;
762 value = sc->copper_queue->status[statnum];
763 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
770 ips_copperhead_intr(void *void_sc)
772 ips_softc_t *sc = (ips_softc_t *)void_sc;
773 ips_cmd_status_t status;
776 lockmgr(&sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
777 while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
778 status.value = ips_copperhead_cmd_status(sc);
779 cmdnumber = status.fields.command_id;
780 sc->commandarray[cmdnumber].status.value = status.value;
781 sc->commandarray[cmdnumber].timeout = 0;
782 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
783 PRINTF(9, "ips: got command %d\n", cmdnumber);
785 lockmgr(&sc->queue_lock, LK_RELEASE);
790 ips_issue_copperhead_cmd(ips_command_t *command)
795 /* hmmm, is there a cleaner way to do this? */
796 if (command->sc->state & IPS_OFFLINE) {
798 command->status.value = IPS_ERROR_STATUS;
799 command->callback(command);
802 command->timeout = 10;
803 for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
806 kprintf("sem bit still set, can't send a command\n");
810 DELAY(500); /* need to do a delay here */
812 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
813 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
818 ips_copperhead_poll(ips_command_t *command)
820 kprintf("ips: cmd polling not implemented for copperhead devices\n");