xref: /freebsd/sys/dev/ips/ips.c (revision dce6e6518b85561495cff38a3074a69d29d58a55)
1 /*-
2  * Copyright (c) 2002 Adaptec Inc.
3  * All rights reserved.
4  *
5  * Written by: David Jeffery
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 
32 #include <dev/ips/ips.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <machine/clock.h>
36 
37 static d_open_t ips_open;
38 static d_close_t ips_close;
39 static d_ioctl_t ips_ioctl;
40 
41 #define IPS_CDEV_MAJOR 175
42 static struct cdevsw ips_cdevsw = {
43 	.d_open = ips_open,
44 	.d_close = ips_close,
45 	.d_ioctl = ips_ioctl,
46 	.d_name = "ips",
47 	.d_maj = IPS_CDEV_MAJOR,
48 };
49 
50 
51 static int ips_open(dev_t dev, int flags, int fmt, struct thread *td)
52 {
53 	ips_softc_t *sc = dev->si_drv1;
54 	sc->state |= IPS_DEV_OPEN;
55         return 0;
56 }
57 
58 static int ips_close(dev_t dev, int flags, int fmt, struct thread *td)
59 {
60 	ips_softc_t *sc = dev->si_drv1;
61 	sc->state &= ~IPS_DEV_OPEN;
62 
63         return 0;
64 }
65 
66 static int ips_ioctl(dev_t dev, u_long command, caddr_t addr, int32_t flags, struct thread *td)
67 {
68 	ips_softc_t *sc;
69 
70 	sc = dev->si_drv1;
71 	return ips_ioctl_request(sc, command, addr, flags);
72 }
73 
74 static void ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
75 {
76 	ips_command_t *command = cmdptr;
77 	PRINTF(10, "ips: in ips_cmd_dmaload\n");
78 	if(!error)
79 		command->command_phys_addr = segments[0].ds_addr;
80 
81 }
82 
83 /* is locking needed? what locking guarentees are there on removal? */
84 static __inline__ int ips_cmdqueue_free(ips_softc_t *sc)
85 {
86 	int i, error = -1;
87 	intrmask_t mask = splbio();
88 	if(!sc->used_commands){
89 		for(i = 0; i < sc->max_cmds; i++){
90 			if(!(sc->commandarray[i].command_phys_addr))
91 				continue;
92 			bus_dmamap_unload(sc->command_dmatag,
93 					  sc->commandarray[i].command_dmamap);
94 			bus_dmamem_free(sc->command_dmatag,
95 					sc->commandarray[i].command_buffer,
96 					sc->commandarray[i].command_dmamap);
97 		}
98 		error = 0;
99 		sc->state |= IPS_OFFLINE;
100 	}
101 	splx(mask);
102 	return error;
103 }
104 
105 /* places all ips command structs on the free command queue.  No locking as if someone else tries
106  * to access this during init, we have bigger problems */
107 static __inline__ int ips_cmdqueue_init(ips_softc_t *sc)
108 {
109 	int i;
110 	ips_command_t *command;
111 	SLIST_INIT(&sc->free_cmd_list);
112 	STAILQ_INIT(&sc->cmd_wait_list);
113 	for(i = 0; i < sc->max_cmds; i++){
114 		sc->commandarray[i].id = i;
115 		sc->commandarray[i].sc = sc;
116 		SLIST_INSERT_HEAD(&sc->free_cmd_list, &sc->commandarray[i],
117 				  next);
118 	}
119 	for(i = 0; i < sc->max_cmds; i++){
120 		command = &sc->commandarray[i];
121 		if(bus_dmamem_alloc(sc->command_dmatag,&command->command_buffer,
122 		    BUS_DMA_NOWAIT, &command->command_dmamap))
123 			goto error;
124 		bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
125 				command->command_buffer,IPS_COMMAND_LEN,
126 				ips_cmd_dmaload, command, BUS_DMA_NOWAIT);
127 		if(!command->command_phys_addr){
128 			bus_dmamem_free(sc->command_dmatag,
129 			    command->command_buffer, command->command_dmamap);
130 			goto error;
131 		}
132 	}
133 	sc->state &= ~IPS_OFFLINE;
134 	return 0;
135 error:
136 		ips_cmdqueue_free(sc);
137 		return ENOMEM;
138 }
139 
140 static int ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags)
141 {
142 	intrmask_t mask;
143 	ips_command_t *command;
144 	ips_wait_list_t *waiter;
145 	unsigned long memflags = 0;
146 	if(IPS_NOWAIT_FLAG & flags)
147 		memflags = M_NOWAIT;
148 	waiter = malloc(sizeof(ips_wait_list_t), M_DEVBUF, memflags);
149 	if(!waiter)
150 		return ENOMEM;
151 	mask = splbio();
152 	if(sc->state & IPS_OFFLINE){
153 		splx(mask);
154 		return EIO;
155 	}
156 	command = SLIST_FIRST(&sc->free_cmd_list);
157 	if(command && !(sc->state & IPS_TIMEOUT)){
158 		SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
159 		(sc->used_commands)++;
160 		splx(mask);
161 		clear_ips_command(command);
162 		bzero(command->command_buffer, IPS_COMMAND_LEN);
163 		free(waiter, M_DEVBUF);
164 		command->arg = data;
165 		return callback(command);
166 	}
167 	DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
168 	waiter->callback = callback;
169 	waiter->data = data;
170 	STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
171 	splx(mask);
172 	return 0;
173 }
174 
175 static void ips_run_waiting_command(ips_softc_t *sc)
176 {
177 	ips_wait_list_t *waiter;
178 	ips_command_t	*command;
179 	int (*callback)(ips_command_t*);
180 	intrmask_t mask;
181 
182 	mask = splbio();
183 	waiter = STAILQ_FIRST(&sc->cmd_wait_list);
184 	command = SLIST_FIRST(&sc->free_cmd_list);
185 	if(!waiter || !command){
186 		splx(mask);
187 		return;
188 	}
189 	DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
190 	SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
191 	STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
192 	(sc->used_commands)++;
193 	splx(mask);
194 	clear_ips_command(command);
195 	bzero(command->command_buffer, IPS_COMMAND_LEN);
196 	command->arg = waiter->data;
197 	callback = waiter->callback;
198 	free(waiter, M_DEVBUF);
199 	callback(command);
200 	return;
201 }
202 /* returns a free command struct if one is available.
203  * It also blanks out anything that may be a wild pointer/value.
204  * Also, command buffers are not freed.  They are
205  * small so they are saved and kept dmamapped and loaded.
206  */
207 int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags)
208 {
209 	intrmask_t mask;
210 	ips_command_t *command;
211 	mask = splbio();
212 
213 	if(sc->state & IPS_OFFLINE){
214 		splx(mask);
215 		return EIO;
216 	}
217 	command = SLIST_FIRST(&sc->free_cmd_list);
218 	if(!command || (sc->state & IPS_TIMEOUT)){
219 		splx(mask);
220 		if(flags & IPS_NOWAIT_FLAG)
221 			return EAGAIN;
222 		return ips_add_waiting_command(sc, callback, data, flags);
223 	}
224 	SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
225 	(sc->used_commands)++;
226 	splx(mask);
227 	clear_ips_command(command);
228 	bzero(command->command_buffer, IPS_COMMAND_LEN);
229 	command->arg = data;
230 	return callback(command);
231 }
232 
233 /* adds a command back to the free command queue */
234 void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
235 {
236 	intrmask_t mask;
237 	mask = splbio();
238 	SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
239 	(sc->used_commands)--;
240 	splx(mask);
241 	if(!(sc->state & IPS_TIMEOUT))
242 		ips_run_waiting_command(sc);
243 }
244 
245 static int ips_diskdev_init(ips_softc_t *sc)
246 {
247 	int i;
248 	for(i=0; i < IPS_MAX_NUM_DRIVES; i++){
249 		if(sc->drives[i].state & IPS_LD_OKAY){
250 			sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
251 			device_set_ivars(sc->diskdev[i],(void *)(uintptr_t) i);
252 		}
253 	}
254 	if(bus_generic_attach(sc->dev)){
255 		device_printf(sc->dev, "Attaching bus failed\n");
256 	}
257 	return 0;
258 }
259 
260 static int ips_diskdev_free(ips_softc_t *sc)
261 {
262 	int i;
263 	int error = 0;
264 	for(i = 0; i < IPS_MAX_NUM_DRIVES; i++){
265 		if(sc->diskdev[i])
266 			error = device_delete_child(sc->dev, sc->diskdev[i]);
267 			if(error)
268 				return error;
269 	}
270 	bus_generic_detach(sc->dev);
271 	return 0;
272 }
273 
274 /* ips_timeout is periodically called to make sure no commands sent
275  * to the card have become stuck.  If it finds a stuck command, it
276  * sets a flag so the driver won't start any more commands and then
277  * is periodically called to see if all outstanding commands have
278  * either finished or timed out.  Once timed out, an attempt to
279  * reinitialize the card is made.  If that fails, the driver gives
280  * up and declares the card dead. */
281 static void ips_timeout(void *arg)
282 {
283 	intrmask_t mask;
284 	ips_softc_t *sc = arg;
285 	int i, state = 0;
286 	ips_command_t *command;
287 	command = &sc->commandarray[0];
288 	mask = splbio();
289 	for(i = 0; i < sc->max_cmds; i++){
290 		if(!command[i].timeout){
291 			continue;
292 		}
293 		command[i].timeout--;
294 		if(!command[i].timeout){
295 			if(!(sc->state & IPS_TIMEOUT)){
296 				sc->state |= IPS_TIMEOUT;
297 				device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
298 			}
299 			command[i].status.value = IPS_ERROR_STATUS;
300 			command[i].callback(&command[i]);
301 			/* hmm, this should be enough cleanup */
302 		} else
303 			state = 1;
304 	}
305 	if(!state && (sc->state & IPS_TIMEOUT)){
306 		if(sc->ips_adapter_reinit(sc, 1)){
307 			device_printf(sc->dev, "AIEE! adapter reset failed, giving up and going home! Have a nice day.\n");
308 			sc->state |= IPS_OFFLINE;
309 			sc->state &= ~IPS_TIMEOUT;
310 			/* Grr, I hate this solution. I run waiting commands
311 			   one at a time and error them out just before they
312 			   would go to the card. This sucks. */
313 		} else
314 			sc->state &= ~IPS_TIMEOUT;
315 		ips_run_waiting_command(sc);
316 	}
317 	if (sc->state != IPS_OFFLINE)
318 		sc->timer = timeout(ips_timeout, sc, 10*hz);
319 	splx(mask);
320 }
321 
322 /* check card and initialize it */
323 int ips_adapter_init(ips_softc_t *sc)
324 {
325         int i;
326         DEVICE_PRINTF(1,sc->dev, "initializing\n");
327         if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
328 				/* alignemnt */	1,
329 				/* boundary  */	0,
330 				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
331 				/* highaddr  */	BUS_SPACE_MAXADDR,
332 				/* filter    */	NULL,
333 				/* filterarg */	NULL,
334 				/* maxsize   */	IPS_COMMAND_LEN +
335 						    IPS_MAX_SG_LEN,
336 				/* numsegs   */	1,
337 				/* maxsegsize*/	IPS_COMMAND_LEN +
338 						    IPS_MAX_SG_LEN,
339 				/* flags     */	0,
340 				/* lockfunc  */ busdma_lock_mutex,
341 				/* lockarg   */ &Giant,
342 				&sc->command_dmatag) != 0) {
343                 device_printf(sc->dev, "can't alloc command dma tag\n");
344 		goto error;
345         }
346 	if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
347 				/* alignemnt */	1,
348 				/* boundary  */	0,
349 				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
350 				/* highaddr  */	BUS_SPACE_MAXADDR,
351 				/* filter    */	NULL,
352 				/* filterarg */	NULL,
353 				/* maxsize   */	IPS_MAX_IOBUF_SIZE,
354 				/* numsegs   */	IPS_MAX_SG_ELEMENTS,
355 				/* maxsegsize*/	IPS_MAX_IOBUF_SIZE,
356 				/* flags     */	0,
357 				/* lockfunc  */ busdma_lock_mutex,
358 				/* lockarg   */ &Giant,
359 				&sc->sg_dmatag) != 0) {
360 		device_printf(sc->dev, "can't alloc SG dma tag\n");
361 		goto error;
362 	}
363 	/* create one command buffer until we know how many commands this card
364            can handle */
365 	sc->max_cmds = 1;
366 	ips_cmdqueue_init(sc);
367 	callout_handle_init(&sc->timer);
368 
369 	if(sc->ips_adapter_reinit(sc, 0))
370 		goto error;
371 
372 	mtx_init(&sc->cmd_mtx, "ips command mutex", NULL, MTX_DEF);
373 	if ((i = ips_get_adapter_info(sc)) != 0) {
374 		device_printf(sc->dev, "failed to get adapter configuration data from device (%d)\n", i);
375 		goto error;
376 	}
377  	if ((i = ips_get_drive_info(sc)) != 0) {
378 		device_printf(sc->dev, "failed to get drive configuration data from device (%d)\n", i);
379 		goto error;
380 	}
381 	ips_update_nvram(sc); /* no error check as failure doesn't matter */
382 
383         ips_cmdqueue_free(sc);
384 	if(sc->adapter_info.max_concurrent_cmds)
385         	sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
386 	else
387 		sc->max_cmds = 32;
388         if(ips_cmdqueue_init(sc)){
389 		device_printf(sc->dev, "failed to initialize command buffers\n");
390 		goto error;
391 	}
392         sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
393                                         S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
394 	sc->device_file->si_drv1 = sc;
395 	ips_diskdev_init(sc);
396 	sc->timer = timeout(ips_timeout, sc, 10*hz);
397         return 0;
398 
399 error:
400 	ips_adapter_free(sc);
401 	return ENXIO;
402 }
403 
404 /* see if we should reinitialize the card and wait for it to timeout or complete initialization */
405 int ips_morpheus_reinit(ips_softc_t *sc, int force)
406 {
407         u_int32_t tmp;
408 	int i;
409 
410 	tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
411 	if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
412 	    (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
413 		ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
414 		return 0;
415 	}
416 	ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
417 	ips_read_4(sc, MORPHEUS_REG_OIMR);
418 
419 	device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
420 	ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
421 	DELAY(5000000);
422 	pci_read_config(sc->dev, 0, 4);
423 
424 	tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
425 	for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
426 		DELAY(1000000);
427 		DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
428 		tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
429 	}
430 	if(tmp & MORPHEUS_BIT_POST1)
431 		ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
432 
433         if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
434                 device_printf(sc->dev,"Adapter error during initialization.\n");
435 		return 1;
436         }
437 	for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
438 		DELAY(1000000);
439 		DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
440 		tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
441 	}
442 	if(tmp & MORPHEUS_BIT_POST2)
443 		ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
444 
445 	if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
446 		device_printf(sc->dev, "adapter failed config check\n");
447 		return 1;
448         }
449 	ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
450 	if(force && ips_clear_adapter(sc)){
451 		device_printf(sc->dev, "adapter clear failed\n");
452 		return 1;
453 	}
454 	return 0;
455 }
456 
457 /* clean up so we can unload the driver. */
458 int ips_adapter_free(ips_softc_t *sc)
459 {
460 	int error = 0;
461 	intrmask_t mask;
462 	if(sc->state & IPS_DEV_OPEN)
463 		return EBUSY;
464 	if((error = ips_diskdev_free(sc)))
465 		return error;
466 	if(ips_cmdqueue_free(sc)){
467 		device_printf(sc->dev,
468 		     "trying to exit when command queue is not empty!\n");
469 		return EBUSY;
470 	}
471 	DEVICE_PRINTF(1, sc->dev, "free\n");
472 	mask = splbio();
473 	untimeout(ips_timeout, sc, sc->timer);
474 	splx(mask);
475 	if (mtx_initialized(&sc->cmd_mtx))
476 		mtx_destroy(&sc->cmd_mtx);
477 
478 	if(sc->sg_dmatag)
479 		bus_dma_tag_destroy(sc->sg_dmatag);
480 	if(sc->command_dmatag)
481 		bus_dma_tag_destroy(sc->command_dmatag);
482 	if(sc->device_file)
483 	        destroy_dev(sc->device_file);
484         return 0;
485 }
486 
487 void ips_morpheus_intr(void *void_sc)
488 {
489         ips_softc_t *sc = (ips_softc_t *)void_sc;
490 	u_int32_t oisr, iisr;
491 	int cmdnumber;
492 	ips_cmd_status_t status;
493 
494 	iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
495 	oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
496         PRINTF(9,"interrupt registers in:%x out:%x\n",iisr, oisr);
497 	if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
498 		DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
499 		return;
500 	}
501 	while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
502 		cmdnumber = status.fields.command_id;
503 		sc->commandarray[cmdnumber].status.value = status.value;
504 		sc->commandarray[cmdnumber].timeout = 0;
505 		sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
506 
507 
508 		DEVICE_PRINTF(9,sc->dev, "got command %d\n", cmdnumber);
509 	}
510         return;
511 }
512 
513 void ips_issue_morpheus_cmd(ips_command_t *command)
514 {
515 	intrmask_t mask = splbio();
516 	/* hmmm, is there a cleaner way to do this? */
517 	if(command->sc->state & IPS_OFFLINE){
518 		splx(mask);
519 		command->status.value = IPS_ERROR_STATUS;
520 		command->callback(command);
521 		return;
522 	}
523 	command->timeout = 10;
524 	ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
525 	splx(mask);
526 }
527 
528 static void ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,int segnum, int error)
529 {
530 	ips_copper_queue_t *queue = queueptr;
531 	if(error){
532 		return;
533 	}
534 	queue->base_phys_addr = segments[0].ds_addr;
535 }
536 
537 static int ips_copperhead_queue_init(ips_softc_t *sc)
538 {
539 	int error;
540 	bus_dma_tag_t dmatag;
541 	bus_dmamap_t dmamap;
542        	if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
543 				/* alignemnt */	1,
544 				/* boundary  */	0,
545 				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
546 				/* highaddr  */	BUS_SPACE_MAXADDR,
547 				/* filter    */	NULL,
548 				/* filterarg */	NULL,
549 				/* maxsize   */	sizeof(ips_copper_queue_t),
550 				/* numsegs   */	1,
551 				/* maxsegsize*/	sizeof(ips_copper_queue_t),
552 				/* flags     */	0,
553 				/* lockfunc  */ busdma_lock_mutex,
554 				/* lockarg   */ &Giant,
555 				&dmatag) != 0) {
556                 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
557 		error = ENOMEM;
558 		goto exit;
559         }
560 	if(bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
561 	   		    BUS_DMA_NOWAIT, &dmamap)){
562 		error = ENOMEM;
563 		goto exit;
564 	}
565 	bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
566 	sc->copper_queue->dmatag = dmatag;
567 	sc->copper_queue->dmamap = dmamap;
568 	sc->copper_queue->nextstatus = 1;
569 	bus_dmamap_load(dmatag, dmamap,
570 			&(sc->copper_queue->status[0]), IPS_MAX_CMD_NUM * 4,
571 			ips_copperhead_queue_callback, sc->copper_queue,
572 			BUS_DMA_NOWAIT);
573 	if(sc->copper_queue->base_phys_addr == 0){
574 		error = ENOMEM;
575 		goto exit;
576 	}
577 	ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
578 	ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
579 		    IPS_MAX_CMD_NUM * 4);
580 	ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
581 	ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
582 
583 
584 	return 0;
585 exit:
586 	bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
587 	bus_dma_tag_destroy(dmatag);
588 	return error;
589 }
590 
591 /* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */
592 int ips_copperhead_reinit(ips_softc_t *sc, int force)
593 {
594 	int i, j;
595 	u_int32_t postcode = 0, configstatus = 0;
596 	ips_write_1(sc, COPPER_REG_SCPR, 0x80);
597 	ips_write_1(sc, COPPER_REG_SCPR, 0);
598 	device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n");
599 	for(j = 0; j < 2; j++){
600 		postcode <<= 8;
601 		for(i = 0; i < 45; i++){
602 			if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
603 				postcode |= ips_read_1(sc, COPPER_REG_ISPR);
604 				ips_write_1(sc, COPPER_REG_HISR,
605 					    COPPER_GHI_BIT);
606 				break;
607 			} else
608 				DELAY(1000000);
609 		}
610 		if(i == 45)
611 			return 1;
612 	}
613 	for(j = 0; j < 2; j++){
614 		configstatus <<= 8;
615 		for(i = 0; i < 240; i++){
616 			if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
617 				configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
618 				ips_write_1(sc, COPPER_REG_HISR,
619 					    COPPER_GHI_BIT);
620 				break;
621 			} else
622 				DELAY(1000000);
623 		}
624 		if(i == 240)
625 			return 1;
626 	}
627 	for(i = 0; i < 240; i++){
628 		if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){
629 			break;
630 		} else
631 			DELAY(1000000);
632 	}
633 	if(i == 240)
634 		return 1;
635 	ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
636 	ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
637 	ips_copperhead_queue_init(sc);
638 	ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
639 	i = ips_read_1(sc, COPPER_REG_SCPR);
640 	ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
641 	if(!configstatus){
642 		device_printf(sc->dev, "adapter initialization failed\n");
643 		return 1;
644 	}
645 	if(force && ips_clear_adapter(sc)){
646 		device_printf(sc->dev, "adapter clear failed\n");
647 		return 1;
648 	}
649 	return 0;
650 }
651 static u_int32_t ips_copperhead_cmd_status(ips_softc_t *sc)
652 {
653 	intrmask_t mask;
654 	u_int32_t value;
655 	int statnum = sc->copper_queue->nextstatus++;
656 	if(sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
657 		sc->copper_queue->nextstatus = 0;
658 	mask = splbio();
659 	value = sc->copper_queue->status[statnum];
660 	ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
661 		    4 * statnum);
662 	splx(mask);
663 	return value;
664 }
665 
666 
667 void ips_copperhead_intr(void *void_sc)
668 {
669         ips_softc_t *sc = (ips_softc_t *)void_sc;
670 	int cmdnumber;
671 	ips_cmd_status_t status;
672 
673 	while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){
674 		status.value = ips_copperhead_cmd_status(sc);
675 		cmdnumber = status.fields.command_id;
676 		sc->commandarray[cmdnumber].status.value = status.value;
677 		sc->commandarray[cmdnumber].timeout = 0;
678 		sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
679 		PRINTF(9, "ips: got command %d\n", cmdnumber);
680 	}
681         return;
682 }
683 
684 void ips_issue_copperhead_cmd(ips_command_t *command)
685 {
686 	int i;
687 	intrmask_t mask = splbio();
688 	/* hmmm, is there a cleaner way to do this? */
689 	if(command->sc->state & IPS_OFFLINE){
690 		splx(mask);
691 		command->status.value = IPS_ERROR_STATUS;
692 		command->callback(command);
693 		return;
694 	}
695 	command->timeout = 10;
696 	for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
697 	    i++ ){
698 		if( i == 20){
699 printf("sem bit still set, can't send a command\n");
700 			splx(mask);
701 			return;
702 		}
703 		DELAY(500);/* need to do a delay here */
704 	}
705 	ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
706 	ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
707 	splx(mask);
708 }
709 
710