FreeBSD/Linux Kernel Cross Reference
sys/dev/ips/ips.c
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: releng/5.1/sys/dev/ips/ips.c 114902 2003-05-11 06:36:49Z scottl $
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 *) 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 DEVICE_PRINTF(1,sc->dev, "initializing\n");
326 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
327 /* alignemnt */ 1,
328 /* boundary */ 0,
329 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
330 /* highaddr */ BUS_SPACE_MAXADDR,
331 /* filter */ NULL,
332 /* filterarg */ NULL,
333 /* maxsize */ IPS_COMMAND_LEN +
334 IPS_MAX_SG_LEN,
335 /* numsegs */ 1,
336 /* maxsegsize*/ IPS_COMMAND_LEN +
337 IPS_MAX_SG_LEN,
338 /* flags */ 0,
339 &sc->command_dmatag) != 0) {
340 device_printf(sc->dev, "can't alloc command dma tag\n");
341 goto error;
342 }
343 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
344 /* alignemnt */ 1,
345 /* boundary */ 0,
346 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
347 /* highaddr */ BUS_SPACE_MAXADDR,
348 /* filter */ NULL,
349 /* filterarg */ NULL,
350 /* maxsize */ IPS_MAX_IOBUF_SIZE,
351 /* numsegs */ IPS_MAX_SG_ELEMENTS,
352 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
353 /* flags */ 0,
354 &sc->sg_dmatag) != 0) {
355 device_printf(sc->dev, "can't alloc SG dma tag\n");
356 goto error;
357 }
358 /* create one command buffer until we know how many commands this card
359 can handle */
360 sc->max_cmds = 1;
361 ips_cmdqueue_init(sc);
362
363 if(sc->ips_adapter_reinit(sc, 0))
364 goto error;
365
366 mtx_init(&sc->cmd_mtx, "ips command mutex", NULL, MTX_DEF);
367 if(ips_get_adapter_info(sc) || ips_get_drive_info(sc)){
368 device_printf(sc->dev, "failed to get configuration data from device\n");
369 goto error;
370 }
371 ips_update_nvram(sc); /* no error check as failure doesn't matter */
372
373 ips_cmdqueue_free(sc);
374 if(sc->adapter_info.max_concurrent_cmds)
375 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
376 else
377 sc->max_cmds = 32;
378 if(ips_cmdqueue_init(sc)){
379 device_printf(sc->dev, "failed to initialize command buffers\n");
380 goto error;
381 }
382 sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
383 S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
384 sc->device_file->si_drv1 = sc;
385 ips_diskdev_init(sc);
386 sc->timer = timeout(ips_timeout, sc, 10*hz);
387 return 0;
388
389 error:
390 ips_adapter_free(sc);
391 return ENXIO;
392 }
393
394 /* see if we should reinitialize the card and wait for it to timeout or complete initialization */
395 int ips_morpheus_reinit(ips_softc_t *sc, int force)
396 {
397 u_int32_t tmp;
398 int i;
399
400 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
401 if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
402 (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
403 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
404 return 0;
405 }
406 ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
407 ips_read_4(sc, MORPHEUS_REG_OIMR);
408
409 device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
410 ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
411 DELAY(5000000);
412 pci_read_config(sc->dev, 0, 4);
413
414 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
415 for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
416 DELAY(1000000);
417 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
418 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
419 }
420 if(tmp & MORPHEUS_BIT_POST1)
421 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
422
423 if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
424 device_printf(sc->dev,"Adapter error during initialization.\n");
425 return 1;
426 }
427 for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
428 DELAY(1000000);
429 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
430 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
431 }
432 if(tmp & MORPHEUS_BIT_POST2)
433 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
434
435 if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
436 device_printf(sc->dev, "adapter failed config check\n");
437 return 1;
438 }
439 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
440 if(force && ips_clear_adapter(sc)){
441 device_printf(sc->dev, "adapter clear failed\n");
442 return 1;
443 }
444 return 0;
445 }
446
447 /* clean up so we can unload the driver. */
448 int ips_adapter_free(ips_softc_t *sc)
449 {
450 int error = 0;
451 intrmask_t mask;
452 if(sc->state & IPS_DEV_OPEN)
453 return EBUSY;
454 if((error = ips_diskdev_free(sc)))
455 return error;
456 if(ips_cmdqueue_free(sc)){
457 device_printf(sc->dev,
458 "trying to exit when command queue is not empty!\n");
459 return EBUSY;
460 }
461 DEVICE_PRINTF(1, sc->dev, "free\n");
462 mask = splbio();
463 untimeout(ips_timeout, sc, sc->timer);
464 splx(mask);
465 if (mtx_initialized(&sc->cmd_mtx))
466 mtx_destroy(&sc->cmd_mtx);
467
468 if(sc->sg_dmatag)
469 bus_dma_tag_destroy(sc->sg_dmatag);
470 if(sc->command_dmatag)
471 bus_dma_tag_destroy(sc->command_dmatag);
472 if(sc->device_file)
473 destroy_dev(sc->device_file);
474 return 0;
475 }
476
477 void ips_morpheus_intr(void *void_sc)
478 {
479 ips_softc_t *sc = (ips_softc_t *)void_sc;
480 u_int32_t oisr, iisr;
481 int cmdnumber;
482 ips_cmd_status_t status;
483
484 iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
485 oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
486 PRINTF(9,"interrupt registers in:%x out:%x\n",iisr, oisr);
487 if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
488 DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
489 return;
490 }
491 while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
492 cmdnumber = status.fields.command_id;
493 sc->commandarray[cmdnumber].status.value = status.value;
494 sc->commandarray[cmdnumber].timeout = 0;
495 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
496
497
498 DEVICE_PRINTF(9,sc->dev, "got command %d\n", cmdnumber);
499 }
500 return;
501 }
502
503 void ips_issue_morpheus_cmd(ips_command_t *command)
504 {
505 intrmask_t mask = splbio();
506 /* hmmm, is there a cleaner way to do this? */
507 if(command->sc->state & IPS_OFFLINE){
508 splx(mask);
509 command->status.value = IPS_ERROR_STATUS;
510 command->callback(command);
511 return;
512 }
513 command->timeout = 10;
514 ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
515 splx(mask);
516 }
517
518 static void ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,int segnum, int error)
519 {
520 ips_copper_queue_t *queue = queueptr;
521 if(error){
522 return;
523 }
524 queue->base_phys_addr = segments[0].ds_addr;
525 }
526
527 static int ips_copperhead_queue_init(ips_softc_t *sc)
528 {
529 int error;
530 bus_dma_tag_t dmatag;
531 bus_dmamap_t dmamap;
532 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
533 /* alignemnt */ 1,
534 /* boundary */ 0,
535 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
536 /* highaddr */ BUS_SPACE_MAXADDR,
537 /* filter */ NULL,
538 /* filterarg */ NULL,
539 /* maxsize */ sizeof(ips_copper_queue_t),
540 /* numsegs */ 1,
541 /* maxsegsize*/ sizeof(ips_copper_queue_t),
542 /* flags */ 0,
543 &dmatag) != 0) {
544 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
545 error = ENOMEM;
546 goto exit;
547 }
548 if(bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
549 BUS_DMA_NOWAIT, &dmamap)){
550 error = ENOMEM;
551 goto exit;
552 }
553 bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
554 sc->copper_queue->dmatag = dmatag;
555 sc->copper_queue->dmamap = dmamap;
556 sc->copper_queue->nextstatus = 1;
557 bus_dmamap_load(dmatag, dmamap,
558 &(sc->copper_queue->status[0]), IPS_MAX_CMD_NUM * 4,
559 ips_copperhead_queue_callback, sc->copper_queue,
560 BUS_DMA_NOWAIT);
561 if(sc->copper_queue->base_phys_addr == 0){
562 error = ENOMEM;
563 goto exit;
564 }
565 ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
566 ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
567 IPS_MAX_CMD_NUM * 4);
568 ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
569 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
570
571
572 return 0;
573 exit:
574 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
575 bus_dma_tag_destroy(dmatag);
576 return error;
577 }
578
579 /* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */
580 int ips_copperhead_reinit(ips_softc_t *sc, int force)
581 {
582 int i, j;
583 u_int32_t postcode = 0, configstatus = 0;
584 ips_write_1(sc, COPPER_REG_SCPR, 0x80);
585 ips_write_1(sc, COPPER_REG_SCPR, 0);
586 device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n");
587 for(j = 0; j < 2; j++){
588 postcode <<= 8;
589 for(i = 0; i < 45; i++){
590 if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
591 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
592 ips_write_1(sc, COPPER_REG_HISR,
593 COPPER_GHI_BIT);
594 break;
595 } else
596 DELAY(1000000);
597 }
598 if(i == 45)
599 return 1;
600 }
601 for(j = 0; j < 2; j++){
602 configstatus <<= 8;
603 for(i = 0; i < 240; i++){
604 if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
605 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
606 ips_write_1(sc, COPPER_REG_HISR,
607 COPPER_GHI_BIT);
608 break;
609 } else
610 DELAY(1000000);
611 }
612 if(i == 240)
613 return 1;
614 }
615 for(i = 0; i < 240; i++){
616 if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){
617 break;
618 } else
619 DELAY(1000000);
620 }
621 if(i == 240)
622 return 1;
623 ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
624 ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
625 ips_copperhead_queue_init(sc);
626 ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
627 i = ips_read_1(sc, COPPER_REG_SCPR);
628 ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
629 if(!configstatus){
630 device_printf(sc->dev, "adapter initialization failed\n");
631 return 1;
632 }
633 if(force && ips_clear_adapter(sc)){
634 device_printf(sc->dev, "adapter clear failed\n");
635 return 1;
636 }
637 return 0;
638 }
639 static u_int32_t ips_copperhead_cmd_status(ips_softc_t *sc)
640 {
641 intrmask_t mask;
642 u_int32_t value;
643 int statnum = sc->copper_queue->nextstatus++;
644 if(sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
645 sc->copper_queue->nextstatus = 0;
646 mask = splbio();
647 value = sc->copper_queue->status[statnum];
648 ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
649 4 * statnum);
650 splx(mask);
651 return value;
652 }
653
654
655 void ips_copperhead_intr(void *void_sc)
656 {
657 ips_softc_t *sc = (ips_softc_t *)void_sc;
658 int cmdnumber;
659 ips_cmd_status_t status;
660
661 while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){
662 status.value = ips_copperhead_cmd_status(sc);
663 cmdnumber = status.fields.command_id;
664 sc->commandarray[cmdnumber].status.value = status.value;
665 sc->commandarray[cmdnumber].timeout = 0;
666 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
667 PRINTF(9, "ips: got command %d\n", cmdnumber);
668 }
669 return;
670 }
671
672 void ips_issue_copperhead_cmd(ips_command_t *command)
673 {
674 int i;
675 intrmask_t mask = splbio();
676 /* hmmm, is there a cleaner way to do this? */
677 if(command->sc->state & IPS_OFFLINE){
678 splx(mask);
679 command->status.value = IPS_ERROR_STATUS;
680 command->callback(command);
681 return;
682 }
683 command->timeout = 10;
684 for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
685 i++ ){
686 if( i == 20){
687 printf("sem bit still set, can't send a command\n");
688 splx(mask);
689 return;
690 }
691 DELAY(500);/* need to do a delay here */
692 }
693 ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
694 ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
695 splx(mask);
696 }
697
Cache object: da644ce2d3236be9c51f0f868538a78f
|