vpoio.c (55205) | vpoio.c (55939) |
---|---|
1/*- | 1/*- |
2 * Copyright (c) 1998 Nicolas Souchu | 2 * Copyright (c) 1998, 1999 Nicolas Souchu |
3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/dev/ppbus/vpoio.c 55205 1999-12-29 04:46:21Z peter $ | 26 * $FreeBSD: head/sys/dev/ppbus/vpoio.c 55939 2000-01-14 00:18:06Z nsouch $ |
27 * 28 */ 29 30#ifdef _KERNEL 31#include <sys/param.h> 32#include <sys/systm.h> | 27 * 28 */ 29 30#ifdef _KERNEL 31#include <sys/param.h> 32#include <sys/systm.h> |
33#include <sys/module.h> 34#include <sys/bus.h> |
|
33#include <sys/malloc.h> 34#include <sys/buf.h> 35 36#include <machine/clock.h> 37 38#endif 39 40#ifdef _KERNEL 41#include <sys/kernel.h> 42#endif 43 44#include "opt_vpo.h" 45 | 35#include <sys/malloc.h> 36#include <sys/buf.h> 37 38#include <machine/clock.h> 39 40#endif 41 42#ifdef _KERNEL 43#include <sys/kernel.h> 44#endif 45 46#include "opt_vpo.h" 47 |
48#include <dev/ppbus/ppbio.h> |
|
46#include <dev/ppbus/ppbconf.h> 47#include <dev/ppbus/ppb_msq.h> 48#include <dev/ppbus/vpoio.h> 49 | 49#include <dev/ppbus/ppbconf.h> 50#include <dev/ppbus/ppb_msq.h> 51#include <dev/ppbus/vpoio.h> 52 |
53#include "ppbus_if.h" 54 |
|
50/* 51 * The driver pools the drive. We may add a timeout queue to avoid 52 * active polling on nACK. I've tried this but it leads to unreliable 53 * transfers 54 */ 55#define VP0_SELTMO 5000 /* select timeout */ 56#define VP0_FAST_SPINTMO 500000 /* wait status timeout */ 57#define VP0_LOW_SPINTMO 5000000 /* wait status timeout */ --- 208 unchanged lines hidden (view full) --- 266 MS_RET(1), 267/* error: */ 268 MS_RET(0) 269}; 270 271static int 272vpoio_disconnect(struct vpoio_data *vpo) 273{ | 55/* 56 * The driver pools the drive. We may add a timeout queue to avoid 57 * active polling on nACK. I've tried this but it leads to unreliable 58 * transfers 59 */ 60#define VP0_SELTMO 5000 /* select timeout */ 61#define VP0_FAST_SPINTMO 500000 /* wait status timeout */ 62#define VP0_LOW_SPINTMO 5000000 /* wait status timeout */ --- 208 unchanged lines hidden (view full) --- 271 MS_RET(1), 272/* error: */ 273 MS_RET(0) 274}; 275 276static int 277vpoio_disconnect(struct vpoio_data *vpo) 278{ |
279 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
274 int ret; 275 | 280 int ret; 281 |
276 ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret); 277 return (ppb_release_bus(&vpo->vpo_dev)); | 282 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); 283 return (ppb_release_bus(ppbus, vpo->vpo_dev)); |
278} 279 280/* 281 * how : PPB_WAIT or PPB_DONTWAIT 282 */ 283static int 284vpoio_connect(struct vpoio_data *vpo, int how) 285{ | 284} 285 286/* 287 * how : PPB_WAIT or PPB_DONTWAIT 288 */ 289static int 290vpoio_connect(struct vpoio_data *vpo, int how) 291{ |
292 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
286 int error; 287 int ret; 288 | 293 int error; 294 int ret; 295 |
289 if ((error = ppb_request_bus(&vpo->vpo_dev, how))) { | 296 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, how))) { |
290 291#ifdef VP0_DEBUG 292 printf("%s: can't request bus!\n", __FUNCTION__); 293#endif 294 return error; 295 } 296 | 297 298#ifdef VP0_DEBUG 299 printf("%s: can't request bus!\n", __FUNCTION__); 300#endif 301 return error; 302 } 303 |
297 if (PPB_IN_EPP_MODE(&vpo->vpo_dev)) 298 ppb_MS_microseq(&vpo->vpo_dev, connect_epp_microseq, &ret); | 304 if (PPB_IN_EPP_MODE(ppbus)) 305 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret); |
299 else | 306 else |
300 ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret); | 307 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); |
301 302 return (0); 303} 304 305/* 306 * vpoio_reset() 307 * 308 * SCSI reset signal, the drive must be in disk mode 309 */ 310static void 311vpoio_reset (struct vpoio_data *vpo) 312{ | 308 309 return (0); 310} 311 312/* 313 * vpoio_reset() 314 * 315 * SCSI reset signal, the drive must be in disk mode 316 */ 317static void 318vpoio_reset (struct vpoio_data *vpo) 319{ |
320 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
313 int ret; 314 315 struct ppb_microseq reset_microseq[] = { 316 317 #define INITIATOR MS_PARAM(0, 1, MS_TYP_INT) 318 319 MS_DASS(MS_UNKNOWN), 320 MS_CASS(H_AUTO | H_nSELIN | H_nINIT | H_STROBE), 321 MS_DELAY(25), 322 MS_CASS(H_AUTO | H_nSELIN | H_INIT | H_STROBE), 323 MS_RET(0) 324 }; 325 326 ppb_MS_init_msq(reset_microseq, 1, INITIATOR, 1 << VP0_INITIATOR); | 321 int ret; 322 323 struct ppb_microseq reset_microseq[] = { 324 325 #define INITIATOR MS_PARAM(0, 1, MS_TYP_INT) 326 327 MS_DASS(MS_UNKNOWN), 328 MS_CASS(H_AUTO | H_nSELIN | H_nINIT | H_STROBE), 329 MS_DELAY(25), 330 MS_CASS(H_AUTO | H_nSELIN | H_INIT | H_STROBE), 331 MS_RET(0) 332 }; 333 334 ppb_MS_init_msq(reset_microseq, 1, INITIATOR, 1 << VP0_INITIATOR); |
327 ppb_MS_microseq(&vpo->vpo_dev, reset_microseq, &ret); | 335 ppb_MS_microseq(ppbus, vpo->vpo_dev, reset_microseq, &ret); |
328 329 return; 330} 331 332/* 333 * vpoio_in_disk_mode() 334 */ 335static int 336vpoio_in_disk_mode(struct vpoio_data *vpo) 337{ | 336 337 return; 338} 339 340/* 341 * vpoio_in_disk_mode() 342 */ 343static int 344vpoio_in_disk_mode(struct vpoio_data *vpo) 345{ |
346 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
338 int ret; 339 | 347 int ret; 348 |
340 ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); | 349 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); |
341 342 return (ret); 343} 344 345/* 346 * vpoio_detect() 347 * 348 * Detect and initialise the VP0 adapter. 349 */ 350static int 351vpoio_detect(struct vpoio_data *vpo) 352{ | 350 351 return (ret); 352} 353 354/* 355 * vpoio_detect() 356 * 357 * Detect and initialise the VP0 adapter. 358 */ 359static int 360vpoio_detect(struct vpoio_data *vpo) 361{ |
362 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
353 int error, ret; 354 355 /* allocate the bus, then apply microsequences */ | 363 int error, ret; 364 365 /* allocate the bus, then apply microsequences */ |
356 if ((error = ppb_request_bus(&vpo->vpo_dev, PPB_DONTWAIT))) | 366 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT))) |
357 return (error); 358 | 367 return (error); 368 |
359 ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret); | 369 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); |
360 | 370 |
361 if (PPB_IN_EPP_MODE(&vpo->vpo_dev)) 362 ppb_MS_microseq(&vpo->vpo_dev, connect_epp_microseq, &ret); | 371 if (PPB_IN_EPP_MODE(ppbus)) 372 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret); |
363 else | 373 else |
364 ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret); | 374 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); |
365 | 375 |
366 ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); | 376 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); |
367 if (!ret) { 368 369 /* try spp mode (maybe twice or because previous mode was PS2) 370 * NIBBLE mode will be restored on next transfers if detection 371 * succeed 372 */ | 377 if (!ret) { 378 379 /* try spp mode (maybe twice or because previous mode was PS2) 380 * NIBBLE mode will be restored on next transfers if detection 381 * succeed 382 */ |
373 ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE); 374 ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret); | 383 ppb_set_mode(ppbus, PPB_NIBBLE); 384 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); |
375 | 385 |
376 ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); | 386 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); |
377 if (!ret) { 378 if (bootverbose) 379 printf("vpo%d: can't connect to the drive\n", 380 vpo->vpo_unit); 381 382 /* disconnect and release the bus */ | 387 if (!ret) { 388 if (bootverbose) 389 printf("vpo%d: can't connect to the drive\n", 390 vpo->vpo_unit); 391 392 /* disconnect and release the bus */ |
383 ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, | 393 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, |
384 &ret); 385 goto error; 386 } 387 } 388 389 /* send SCSI reset signal */ 390 vpoio_reset(vpo); 391 | 394 &ret); 395 goto error; 396 } 397 } 398 399 /* send SCSI reset signal */ 400 vpoio_reset(vpo); 401 |
392 ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret); | 402 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); |
393 394 /* ensure we are disconnected or daisy chained peripheral 395 * may cause serious problem to the disk */ 396 | 403 404 /* ensure we are disconnected or daisy chained peripheral 405 * may cause serious problem to the disk */ 406 |
397 ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret); | 407 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); |
398 if (ret) { 399 if (bootverbose) 400 printf("vpo%d: can't disconnect from the drive\n", 401 vpo->vpo_unit); 402 goto error; 403 } 404 | 408 if (ret) { 409 if (bootverbose) 410 printf("vpo%d: can't disconnect from the drive\n", 411 vpo->vpo_unit); 412 goto error; 413 } 414 |
405 ppb_release_bus(&vpo->vpo_dev); | 415 ppb_release_bus(ppbus, vpo->vpo_dev); |
406 return (0); 407 408error: | 416 return (0); 417 418error: |
409 ppb_release_bus(&vpo->vpo_dev); | 419 ppb_release_bus(ppbus, vpo->vpo_dev); |
410 return (VP0_EINITFAILED); 411} 412 413/* 414 * vpoio_outstr() 415 */ 416static int 417vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size) 418{ | 420 return (VP0_EINITFAILED); 421} 422 423/* 424 * vpoio_outstr() 425 */ 426static int 427vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size) 428{ |
419 | 429 device_t ppbus = device_get_parent(vpo->vpo_dev); |
420 int error = 0; 421 | 430 int error = 0; 431 |
422 ppb_MS_exec(&vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer, | 432 ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer, |
423 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 424 425#if 0 426 /* XXX EPP 1.9 not implemented with microsequences */ 427 else { 428 | 433 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 434 435#if 0 436 /* XXX EPP 1.9 not implemented with microsequences */ 437 else { 438 |
429 ppb_reset_epp_timeout(&vpo->vpo_dev); 430 ppb_wctr(&vpo->vpo_dev, 431 H_AUTO | H_SELIN | H_INIT | H_STROBE); | 439 ppb_reset_epp_timeout(ppbus); 440 ppb_wctr(ppbus, H_AUTO | H_SELIN | H_INIT | H_STROBE); |
432 433 if (((long) buffer | size) & 0x03) | 441 442 if (((long) buffer | size) & 0x03) |
434 ppb_outsb_epp(&vpo->vpo_dev, | 443 ppb_outsb_epp(ppbus, |
435 buffer, size); 436 else | 444 buffer, size); 445 else |
437 ppb_outsl_epp(&vpo->vpo_dev, | 446 ppb_outsl_epp(ppbus, |
438 buffer, size/4); 439 | 447 buffer, size/4); 448 |
440 if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) { | 449 if ((ppb_rstr(ppbus) & TIMEOUT)) { |
441 error = VP0_EPPDATA_TIMEOUT; 442 goto error; 443 } 444 | 450 error = VP0_EPPDATA_TIMEOUT; 451 goto error; 452 } 453 |
445 ppb_wctr(&vpo->vpo_dev, 446 H_AUTO | H_nSELIN | H_INIT | H_STROBE); | 454 ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE); |
447 } 448#endif | 455 } 456#endif |
449 ppb_ecp_sync(&vpo->vpo_dev); | 457 ppb_ecp_sync(ppbus); |
450 451 return (error); 452} 453 454/* 455 * vpoio_instr() 456 */ 457static int 458vpoio_instr(struct vpoio_data *vpo, char *buffer, int size) 459{ | 458 459 return (error); 460} 461 462/* 463 * vpoio_instr() 464 */ 465static int 466vpoio_instr(struct vpoio_data *vpo, char *buffer, int size) 467{ |
468 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
460 int error = 0; 461 | 469 int error = 0; 470 |
462 ppb_MS_exec(&vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer, | 471 ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer, |
463 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 464 465#if 0 466 /* XXX EPP 1.9 not implemented with microsequences */ 467 else { 468 | 472 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 473 474#if 0 475 /* XXX EPP 1.9 not implemented with microsequences */ 476 else { 477 |
469 ppb_reset_epp_timeout(&vpo->vpo_dev); 470 ppb_wctr(&vpo->vpo_dev, PCD | | 478 ppb_reset_epp_timeout(ppbus); 479 ppb_wctr(ppbus, PCD | |
471 H_AUTO | H_SELIN | H_INIT | H_STROBE); 472 473 if (((long) buffer | size) & 0x03) | 480 H_AUTO | H_SELIN | H_INIT | H_STROBE); 481 482 if (((long) buffer | size) & 0x03) |
474 ppb_insb_epp(&vpo->vpo_dev, | 483 ppb_insb_epp(ppbus, |
475 buffer, size); 476 else | 484 buffer, size); 485 else |
477 ppb_insl_epp(&vpo->vpo_dev, | 486 ppb_insl_epp(ppbus, |
478 buffer, size/4); 479 | 487 buffer, size/4); 488 |
480 if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) { | 489 if ((ppb_rstr(ppbus) & TIMEOUT)) { |
481 error = VP0_EPPDATA_TIMEOUT; 482 goto error; 483 } 484 | 490 error = VP0_EPPDATA_TIMEOUT; 491 goto error; 492 } 493 |
485 ppb_wctr(&vpo->vpo_dev, PCD | | 494 ppb_wctr(ppbus, PCD | |
486 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 487 } 488#endif | 495 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 496 } 497#endif |
489 ppb_ecp_sync(&vpo->vpo_dev); | 498 ppb_ecp_sync(ppbus); |
490 491 return (error); 492} 493 494static char 495vpoio_select(struct vpoio_data *vpo, int initiator, int target) 496{ | 499 500 return (error); 501} 502 503static char 504vpoio_select(struct vpoio_data *vpo, int initiator, int target) 505{ |
506 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
497 int ret; 498 499 struct ppb_microseq select_microseq[] = { 500 501 /* parameter list 502 */ 503 #define SELECT_TARGET MS_PARAM(0, 1, MS_TYP_INT) 504 #define SELECT_INITIATOR MS_PARAM(3, 1, MS_TYP_INT) --- 13 unchanged lines hidden (view full) --- 518/* ready: */ MS_RET(0) 519 }; 520 521 /* initialize the select microsequence */ 522 ppb_MS_init_msq(select_microseq, 2, 523 SELECT_TARGET, 1 << target, 524 SELECT_INITIATOR, 1 << initiator); 525 | 507 int ret; 508 509 struct ppb_microseq select_microseq[] = { 510 511 /* parameter list 512 */ 513 #define SELECT_TARGET MS_PARAM(0, 1, MS_TYP_INT) 514 #define SELECT_INITIATOR MS_PARAM(3, 1, MS_TYP_INT) --- 13 unchanged lines hidden (view full) --- 528/* ready: */ MS_RET(0) 529 }; 530 531 /* initialize the select microsequence */ 532 ppb_MS_init_msq(select_microseq, 2, 533 SELECT_TARGET, 1 << target, 534 SELECT_INITIATOR, 1 << initiator); 535 |
526 ppb_MS_microseq(&vpo->vpo_dev, select_microseq, &ret); | 536 ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret); |
527 528 if (ret) 529 return (VP0_ESELECT_TIMEOUT); 530 531 return (0); 532} 533 534/* 535 * vpoio_wait() 536 * 537 * H_SELIN must be low. 538 * 539 * XXX should be ported to microseq 540 */ 541static char 542vpoio_wait(struct vpoio_data *vpo, int tmo) 543{ | 537 538 if (ret) 539 return (VP0_ESELECT_TIMEOUT); 540 541 return (0); 542} 543 544/* 545 * vpoio_wait() 546 * 547 * H_SELIN must be low. 548 * 549 * XXX should be ported to microseq 550 */ 551static char 552vpoio_wait(struct vpoio_data *vpo, int tmo) 553{ |
544 | 554 device_t ppbus = device_get_parent(vpo->vpo_dev); |
545 register int k; 546 register char r; 547 548#if 0 /* broken */ | 555 register int k; 556 register char r; 557 558#if 0 /* broken */ |
549 if (ppb_poll_device(&vpo->vpo_dev, 150, nBUSY, nBUSY, PPB_INTR)) | 559 if (ppb_poll_device(ppbus, 150, nBUSY, nBUSY, PPB_INTR)) |
550 return (0); 551 | 560 return (0); 561 |
552 return (ppb_rstr(&vpo->vpo_dev) & 0xf0); | 562 return (ppb_rstr(ppbus) & 0xf0); |
553#endif 554 555 /* XXX should be ported to microseq */ 556 k = 0; | 563#endif 564 565 /* XXX should be ported to microseq */ 566 k = 0; |
557 while (!((r = ppb_rstr(&vpo->vpo_dev)) & nBUSY) && (k++ < tmo)) | 567 while (!((r = ppb_rstr(ppbus)) & nBUSY) && (k++ < tmo)) |
558 ; 559 560 /* 561 * Return some status information. 562 * Semantics : 0xc0 = ZIP wants more data 563 * 0xd0 = ZIP wants to send more data 564 * 0xe0 = ZIP wants command 565 * 0xf0 = end of transfer, ZIP is sending status --- 5 unchanged lines hidden (view full) --- 571} 572 573/* 574 * vpoio_probe() 575 * 576 * Low level probe of vpo device 577 * 578 */ | 568 ; 569 570 /* 571 * Return some status information. 572 * Semantics : 0xc0 = ZIP wants more data 573 * 0xd0 = ZIP wants to send more data 574 * 0xe0 = ZIP wants command 575 * 0xf0 = end of transfer, ZIP is sending status --- 5 unchanged lines hidden (view full) --- 581} 582 583/* 584 * vpoio_probe() 585 * 586 * Low level probe of vpo device 587 * 588 */ |
579struct ppb_device * 580vpoio_probe(struct ppb_data *ppb, struct vpoio_data *vpo) | 589int 590vpoio_probe(device_t dev, struct vpoio_data *vpo) |
581{ | 591{ |
592 int error; |
|
582 583 /* ppbus dependent initialisation */ | 593 594 /* ppbus dependent initialisation */ |
584 vpo->vpo_dev.id_unit = vpo->vpo_unit; 585 vpo->vpo_dev.name = "vpo"; 586 vpo->vpo_dev.ppb = ppb; | 595 vpo->vpo_dev = dev; |
587 588 /* 589 * Initialize microsequence code 590 */ 591 INIT_TRIG_MICROSEQ; 592 593 /* now, try to initialise the drive */ | 596 597 /* 598 * Initialize microsequence code 599 */ 600 INIT_TRIG_MICROSEQ; 601 602 /* now, try to initialise the drive */ |
594 if (vpoio_detect(vpo)) { 595 return (NULL); | 603 if ((error = vpoio_detect(vpo))) { 604 return (error); |
596 } 597 | 605 } 606 |
598 return (&vpo->vpo_dev); | 607 return (0); |
599} 600 601/* 602 * vpoio_attach() 603 * 604 * Low level attachment of vpo device 605 * 606 */ 607int 608vpoio_attach(struct vpoio_data *vpo) 609{ | 608} 609 610/* 611 * vpoio_attach() 612 * 613 * Low level attachment of vpo device 614 * 615 */ 616int 617vpoio_attach(struct vpoio_data *vpo) 618{ |
619 device_t ppbus = device_get_parent(vpo->vpo_dev); |
|
610 int epp; 611 | 620 int epp; 621 |
612 /* 613 * Report ourselves 614 */ 615 printf("vpo%d: <Iomega VPI0 Parallel to SCSI interface> on ppbus %d\n", 616 vpo->vpo_dev.id_unit, vpo->vpo_dev.ppb->ppb_link->adapter_unit); 617 | |
618 vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( 619 sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); 620 621 if (!vpo->vpo_nibble_inbyte_msq) | 622 vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( 623 sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); 624 625 if (!vpo->vpo_nibble_inbyte_msq) |
622 return (0); | 626 return (ENXIO); |
623 624 bcopy((void *)nibble_inbyte_submicroseq, 625 (void *)vpo->vpo_nibble_inbyte_msq, 626 sizeof(nibble_inbyte_submicroseq)); 627 628 INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo); 629 630 /* 631 * Initialize mode dependent in/out microsequences 632 */ | 627 628 bcopy((void *)nibble_inbyte_submicroseq, 629 (void *)vpo->vpo_nibble_inbyte_msq, 630 sizeof(nibble_inbyte_submicroseq)); 631 632 INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo); 633 634 /* 635 * Initialize mode dependent in/out microsequences 636 */ |
633 ppb_request_bus(&vpo->vpo_dev, PPB_WAIT); | 637 ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT); |
634 635 /* enter NIBBLE mode to configure submsq */ | 638 639 /* enter NIBBLE mode to configure submsq */ |
636 if (ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE) != -1) { | 640 if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) { |
637 | 641 |
638 ppb_MS_GET_init(&vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq); | 642 ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq); |
639 | 643 |
640 ppb_MS_PUT_init(&vpo->vpo_dev, spp_outbyte_submicroseq); | 644 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); |
641 } 642 643 /* enter PS2 mode to configure submsq */ | 645 } 646 647 /* enter PS2 mode to configure submsq */ |
644 if (ppb_set_mode(&vpo->vpo_dev, PPB_PS2) != -1) { | 648 if (ppb_set_mode(ppbus, PPB_PS2) != -1) { |
645 | 649 |
646 ppb_MS_GET_init(&vpo->vpo_dev, ps2_inbyte_submicroseq); | 650 ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq); |
647 | 651 |
648 ppb_MS_PUT_init(&vpo->vpo_dev, spp_outbyte_submicroseq); | 652 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); |
649 } 650 | 653 } 654 |
651 epp = ppb_get_epp_protocol(&vpo->vpo_dev); | 655 epp = ppb_get_epp_protocol(ppbus); |
652 653 /* enter EPP mode to configure submsq */ | 656 657 /* enter EPP mode to configure submsq */ |
654 if (ppb_set_mode(&vpo->vpo_dev, PPB_EPP) != -1) { | 658 if (ppb_set_mode(ppbus, PPB_EPP) != -1) { |
655 656 switch (epp) { 657 case EPP_1_9: 658 /* XXX EPP 1.9 support should be improved */ 659 case EPP_1_7: | 659 660 switch (epp) { 661 case EPP_1_9: 662 /* XXX EPP 1.9 support should be improved */ 663 case EPP_1_7: |
660 ppb_MS_GET_init(&vpo->vpo_dev, epp17_instr_body); | 664 ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body); |
661 | 665 |
662 ppb_MS_PUT_init(&vpo->vpo_dev, epp17_outstr_body); | 666 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body); |
663 break; 664 default: 665 panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__, 666 epp); 667 } 668 } 669 670 /* try to enter EPP or PS/2 mode, NIBBLE otherwise */ | 667 break; 668 default: 669 panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__, 670 epp); 671 } 672 } 673 674 /* try to enter EPP or PS/2 mode, NIBBLE otherwise */ |
671 if (ppb_set_mode(&vpo->vpo_dev, PPB_EPP) != -1) { | 675 if (ppb_set_mode(ppbus, PPB_EPP) != -1) { |
672 switch (epp) { 673 case EPP_1_9: 674 printf("vpo%d: EPP 1.9 mode\n", vpo->vpo_unit); 675 break; 676 case EPP_1_7: 677 printf("vpo%d: EPP 1.7 mode\n", vpo->vpo_unit); 678 break; 679 default: 680 panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__, 681 epp); 682 } | 676 switch (epp) { 677 case EPP_1_9: 678 printf("vpo%d: EPP 1.9 mode\n", vpo->vpo_unit); 679 break; 680 case EPP_1_7: 681 printf("vpo%d: EPP 1.7 mode\n", vpo->vpo_unit); 682 break; 683 default: 684 panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__, 685 epp); 686 } |
683 } else if (ppb_set_mode(&vpo->vpo_dev, PPB_PS2) != -1) | 687 } else if (ppb_set_mode(ppbus, PPB_PS2) != -1) |
684 printf("vpo%d: PS2 mode\n", vpo->vpo_unit); 685 | 688 printf("vpo%d: PS2 mode\n", vpo->vpo_unit); 689 |
686 else if (ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE) != -1) | 690 else if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) |
687 printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit); 688 689 else { 690 printf("vpo%d: can't enter NIBBLE, PS2 or EPP mode\n", 691 vpo->vpo_unit); 692 | 691 printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit); 692 693 else { 694 printf("vpo%d: can't enter NIBBLE, PS2 or EPP mode\n", 695 vpo->vpo_unit); 696 |
693 ppb_release_bus(&vpo->vpo_dev); | 697 ppb_release_bus(ppbus, vpo->vpo_dev); |
694 695 free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF); | 698 699 free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF); |
696 return (0); | 700 return (ENXIO); |
697 } 698 | 701 } 702 |
699 ppb_release_bus(&vpo->vpo_dev); | 703 ppb_release_bus(ppbus, vpo->vpo_dev); |
700 | 704 |
701 return (1); | 705 return (0); |
702} 703 704/* 705 * vpoio_reset_bus() 706 * 707 */ 708int 709vpoio_reset_bus(struct vpoio_data *vpo) --- 24 unchanged lines hidden (view full) --- 734 * Send an SCSI command 735 * 736 */ 737int 738vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, 739 int clen, char *buffer, int blen, int *result, int *count, 740 int *ret) 741{ | 706} 707 708/* 709 * vpoio_reset_bus() 710 * 711 */ 712int 713vpoio_reset_bus(struct vpoio_data *vpo) --- 24 unchanged lines hidden (view full) --- 738 * Send an SCSI command 739 * 740 */ 741int 742vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, 743 int clen, char *buffer, int blen, int *result, int *count, 744 int *ret) 745{ |
742 | 746 device_t ppbus = device_get_parent(vpo->vpo_dev); |
743 register char r; 744 char l, h = 0; 745 int len, error = 0; 746 register int k; 747 748 /* 749 * enter disk state, allocate the ppbus 750 * --- 12 unchanged lines hidden (view full) --- 763 if ((*ret = vpoio_select(vpo,host,target))) 764 goto error; 765 766 /* 767 * Send the command ... 768 * 769 * set H_SELIN low for vpoio_wait(). 770 */ | 747 register char r; 748 char l, h = 0; 749 int len, error = 0; 750 register int k; 751 752 /* 753 * enter disk state, allocate the ppbus 754 * --- 12 unchanged lines hidden (view full) --- 767 if ((*ret = vpoio_select(vpo,host,target))) 768 goto error; 769 770 /* 771 * Send the command ... 772 * 773 * set H_SELIN low for vpoio_wait(). 774 */ |
771 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); | 775 ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE); |
772 773 for (k = 0; k < clen; k++) { 774 if (vpoio_wait(vpo, VP0_FAST_SPINTMO) != (char)0xe0) { 775 *ret = VP0_ECMD_TIMEOUT; 776 goto error; 777 } 778 if (vpoio_outstr(vpo, &command[k], 1)) { 779 *ret = VP0_EPPDATA_TIMEOUT; --- 19 unchanged lines hidden (view full) --- 799 if (*count >= blen) { 800 *ret = VP0_EDATA_OVERFLOW; 801 goto error; 802 } 803 804 /* if in EPP mode or writing bytes, try to transfer a sector 805 * otherwise, just send one byte 806 */ | 776 777 for (k = 0; k < clen; k++) { 778 if (vpoio_wait(vpo, VP0_FAST_SPINTMO) != (char)0xe0) { 779 *ret = VP0_ECMD_TIMEOUT; 780 goto error; 781 } 782 if (vpoio_outstr(vpo, &command[k], 1)) { 783 *ret = VP0_EPPDATA_TIMEOUT; --- 19 unchanged lines hidden (view full) --- 803 if (*count >= blen) { 804 *ret = VP0_EDATA_OVERFLOW; 805 goto error; 806 } 807 808 /* if in EPP mode or writing bytes, try to transfer a sector 809 * otherwise, just send one byte 810 */ |
807 if (PPB_IN_EPP_MODE(&vpo->vpo_dev) || r == (char)0xc0) | 811 if (PPB_IN_EPP_MODE(ppbus) || r == (char)0xc0) |
808 len = (((blen - *count) >= VP0_SECTOR_SIZE)) ? 809 VP0_SECTOR_SIZE : 1; 810 else 811 len = 1; 812 813 /* ZIP wants to send data? */ 814 if (r == (char)0xc0) 815 error = vpoio_outstr(vpo, &buffer[*count], len); --- 28 unchanged lines hidden --- | 812 len = (((blen - *count) >= VP0_SECTOR_SIZE)) ? 813 VP0_SECTOR_SIZE : 1; 814 else 815 len = 1; 816 817 /* ZIP wants to send data? */ 818 if (r == (char)0xc0) 819 error = vpoio_outstr(vpo, &buffer[*count], len); --- 28 unchanged lines hidden --- |