ppb_1284.c revision 67164
1157642Sps/*- 2265918Sdavidcs * Copyright (c) 1997 Nicolas Souchu 3157642Sps * All rights reserved. 4157642Sps * 5157642Sps * Redistribution and use in source and binary forms, with or without 6157642Sps * modification, are permitted provided that the following conditions 7157642Sps * are met: 8157642Sps * 1. Redistributions of source code must retain the above copyright 9157642Sps * notice, this list of conditions and the following disclaimer. 10157642Sps * 2. Redistributions in binary form must reproduce the above copyright 11157642Sps * notice, this list of conditions and the following disclaimer in the 12157642Sps * documentation and/or other materials provided with the distribution. 13157642Sps * 14157642Sps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15157642Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16157642Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17157642Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18157642Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19157642Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20157642Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21157642Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22157642Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23157642Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24157642Sps * SUCH DAMAGE. 25157642Sps * 26157642Sps * $FreeBSD: head/sys/dev/ppbus/ppb_1284.c 67164 2000-10-15 14:19:01Z phk $ 27157642Sps * 28189325Sdavidch */ 29189325Sdavidch 30157642Sps/* 31157642Sps * General purpose routines for the IEEE1284-1994 Standard 32157642Sps */ 33157642Sps 34157642Sps#include "opt_ppb_1284.h" 35157642Sps 36157642Sps#include <sys/param.h> 37157642Sps#include <sys/systm.h> 38157642Sps#include <sys/bus.h> 39157642Sps 40157642Sps 41157642Sps#include <dev/ppbus/ppbconf.h> 42157642Sps#include <dev/ppbus/ppb_1284.h> 43169632Sdavidch 44169632Sdavidch#include "ppbus_if.h" 45157642Sps 46157642Sps#include <dev/ppbus/ppbio.h> 47157642Sps 48157642Sps#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev)) 49157642Sps 50157642Sps/* 51157642Sps * do_1284_wait() 52157642Sps * 53157642Sps * Wait for the peripherial up to 40ms 54157642Sps */ 55169632Sdavidchstatic int 56157642Spsdo_1284_wait(device_t bus, char mask, char status) 57169632Sdavidch{ 58169632Sdavidch return (ppb_poll_bus(bus, 4, mask, status, PPB_NOINTR | PPB_POLL)); 59169632Sdavidch} 60170392Sdavidch 61157642Spsstatic int 62157642Spsdo_peripheral_wait(device_t bus, char mask, char status) 63157642Sps{ 64157642Sps return (ppb_poll_bus(bus, 100, mask, status, PPB_NOINTR | PPB_POLL)); 65157642Sps} 66157642Sps 67157642Sps#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4) 68157642Sps 69157642Sps/* 70157642Sps * ppb_1284_reset_error() 71157642Sps * 72157642Sps * Unconditionaly reset the error field 73157642Sps */ 74157642Spsstatic int 75157642Spsppb_1284_reset_error(device_t bus, int state) 76157642Sps{ 77157642Sps struct ppb_data *ppb = DEVTOSOFTC(bus); 78157642Sps 79157642Sps ppb->error = PPB_NO_ERROR; 80206268Sdavidch ppb->state = state; 81206268Sdavidch 82206268Sdavidch return (0); 83157642Sps} 84157642Sps 85157642Sps/* 86157642Sps * ppb_1284_get_state() 87157642Sps * 88157642Sps * Get IEEE1284 state 89157642Sps */ 90157642Spsint 91178132Sdavidchppb_1284_get_state(device_t bus) 92178132Sdavidch{ 93206268Sdavidch return (DEVTOSOFTC(bus)->state); 94206268Sdavidch} 95206268Sdavidch 96206268Sdavidch/* 97206268Sdavidch * ppb_1284_set_state() 98206268Sdavidch * 99206268Sdavidch * Change IEEE1284 state if no error occured 100206268Sdavidch */ 101206268Sdavidchint 102206268Sdavidchppb_1284_set_state(device_t bus, int state) 103206268Sdavidch{ 104206268Sdavidch struct ppb_data *ppb = DEVTOSOFTC(bus); 105206268Sdavidch 106206268Sdavidch /* call ppb_1284_reset_error() if you absolutly want to change 107206268Sdavidch * the state from PPB_ERROR to another */ 108206268Sdavidch if ((ppb->state != PPB_ERROR) && 109206268Sdavidch (ppb->error == PPB_NO_ERROR)) { 110206268Sdavidch ppb->state = state; 111206268Sdavidch ppb->error = PPB_NO_ERROR; 112206268Sdavidch } 113206268Sdavidch 114206268Sdavidch return (0); 115206268Sdavidch} 116206268Sdavidch 117206268Sdavidchstatic int 118206268Sdavidchppb_1284_set_error(device_t bus, int error, int event) 119206268Sdavidch{ 120206268Sdavidch struct ppb_data *ppb = DEVTOSOFTC(bus); 121206268Sdavidch 122206268Sdavidch /* do not accumulate errors */ 123206268Sdavidch if ((ppb->error == PPB_NO_ERROR) && 124206268Sdavidch (ppb->state != PPB_ERROR)) { 125178132Sdavidch ppb->error = error; 126178132Sdavidch ppb->state = PPB_ERROR; 127179771Sdavidch } 128179771Sdavidch 129206268Sdavidch#ifdef DEBUG_1284 130206268Sdavidch printf("ppb1284: error=%d status=0x%x event=%d\n", error, 131206268Sdavidch ppb_rstr(bus) & 0xff, event); 132206268Sdavidch#endif 133206268Sdavidch 134206268Sdavidch return (0); 135206268Sdavidch} 136206268Sdavidch 137206268Sdavidch/* 138206268Sdavidch * ppb_request_mode() 139206268Sdavidch * 140206268Sdavidch * Converts mode+options into ext. value 141206268Sdavidch */ 142206268Sdavidchstatic int 143206268Sdavidchppb_request_mode(int mode, int options) 144206268Sdavidch{ 145179771Sdavidch int request_mode = 0; 146178132Sdavidch 147179771Sdavidch if (options & PPB_EXTENSIBILITY_LINK) { 148179771Sdavidch request_mode = EXT_LINK_1284_NORMAL; 149206268Sdavidch 150206268Sdavidch } else { 151206268Sdavidch switch (mode) { 152206268Sdavidch case PPB_NIBBLE: 153206268Sdavidch request_mode = (options & PPB_REQUEST_ID) ? 154206268Sdavidch NIBBLE_1284_REQUEST_ID : 155206268Sdavidch NIBBLE_1284_NORMAL; 156206268Sdavidch break; 157206268Sdavidch case PPB_PS2: 158206268Sdavidch request_mode = (options & PPB_REQUEST_ID) ? 159206268Sdavidch BYTE_1284_REQUEST_ID : 160206268Sdavidch BYTE_1284_NORMAL; 161206268Sdavidch break; 162206268Sdavidch case PPB_ECP: 163206268Sdavidch if (options & PPB_USE_RLE) 164206268Sdavidch request_mode = (options & PPB_REQUEST_ID) ? 165179771Sdavidch ECP_1284_RLE_REQUEST_ID : 166179771Sdavidch ECP_1284_RLE; 167179771Sdavidch else 168179771Sdavidch request_mode = (options & PPB_REQUEST_ID) ? 169206268Sdavidch ECP_1284_REQUEST_ID : 170206268Sdavidch ECP_1284_NORMAL; 171206268Sdavidch break; 172206268Sdavidch case PPB_EPP: 173206268Sdavidch request_mode = EPP_1284_NORMAL; 174206268Sdavidch break; 175206268Sdavidch default: 176206268Sdavidch panic("%s: unsupported mode %d\n", __FUNCTION__, mode); 177206268Sdavidch } 178206268Sdavidch } 179206268Sdavidch 180206268Sdavidch return (request_mode); 181206268Sdavidch} 182206268Sdavidch 183206268Sdavidch/* 184206268Sdavidch * ppb_peripheral_negociate() 185179771Sdavidch * 186179771Sdavidch * Negociate the peripheral side 187179771Sdavidch */ 188179771Sdavidchint 189206268Sdavidchppb_peripheral_negociate(device_t bus, int mode, int options) 190206268Sdavidch{ 191206268Sdavidch int spin, request_mode, error = 0; 192206268Sdavidch char r; 193206268Sdavidch 194206268Sdavidch ppb_set_mode(bus, PPB_COMPATIBLE); 195206268Sdavidch ppb_1284_set_state(bus, PPB_PERIPHERAL_NEGOCIATION); 196206268Sdavidch 197206268Sdavidch /* compute ext. value */ 198206268Sdavidch request_mode = ppb_request_mode(mode, options); 199206268Sdavidch 200206268Sdavidch /* wait host */ 201206268Sdavidch spin = 10; 202206268Sdavidch while (spin-- && (ppb_rstr(bus) & nBUSY)) 203206268Sdavidch DELAY(1); 204206268Sdavidch 205179771Sdavidch /* check termination */ 206179771Sdavidch if (!(ppb_rstr(bus) & SELECT) || !spin) { 207179771Sdavidch error = ENODEV; 208179771Sdavidch goto error; 209206268Sdavidch } 210206268Sdavidch 211206268Sdavidch /* Event 4 - read ext. value */ 212206268Sdavidch r = ppb_rdtr(bus); 213206268Sdavidch 214206268Sdavidch /* nibble mode is not supported */ 215206268Sdavidch if ((r == (char)request_mode) || 216206268Sdavidch (r == NIBBLE_1284_NORMAL)) { 217206268Sdavidch 218206268Sdavidch /* Event 5 - restore direction bit, no data avail */ 219206268Sdavidch ppb_wctr(bus, (STROBE | nINIT) & ~(SELECTIN)); 220206268Sdavidch DELAY(1); 221206268Sdavidch 222206268Sdavidch /* Event 6 */ 223206268Sdavidch ppb_wctr(bus, (nINIT) & ~(SELECTIN | STROBE)); 224206268Sdavidch 225179771Sdavidch if (r == NIBBLE_1284_NORMAL) { 226179771Sdavidch#ifdef DEBUG_1284 227179771Sdavidch printf("R"); 228179771Sdavidch#endif 229206268Sdavidch ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4); 230206268Sdavidch error = EINVAL; 231206268Sdavidch goto error; 232206268Sdavidch } else { 233206268Sdavidch ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE); 234206268Sdavidch switch (r) { 235206268Sdavidch case BYTE_1284_NORMAL: 236206268Sdavidch ppb_set_mode(bus, PPB_BYTE); 237179771Sdavidch break; 238179771Sdavidch default: 239179771Sdavidch break; 240179771Sdavidch } 241206268Sdavidch#ifdef DEBUG_1284 242206268Sdavidch printf("A"); 243206268Sdavidch#endif 244206268Sdavidch /* negociation succeeds */ 245206268Sdavidch } 246206268Sdavidch } else { 247206268Sdavidch /* Event 5 - mode not supported */ 248206268Sdavidch ppb_wctr(bus, SELECTIN); 249206268Sdavidch DELAY(1); 250206268Sdavidch 251206268Sdavidch /* Event 6 */ 252206268Sdavidch ppb_wctr(bus, (SELECTIN) & ~(STROBE | nINIT)); 253206268Sdavidch ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4); 254206268Sdavidch 255206268Sdavidch#ifdef DEBUG_1284 256206268Sdavidch printf("r"); 257179771Sdavidch#endif 258179771Sdavidch error = EINVAL; 259179771Sdavidch goto error; 260179771Sdavidch } 261206268Sdavidch 262206268Sdavidch return (0); 263206268Sdavidch 264206268Sdavidcherror: 265206268Sdavidch ppb_peripheral_terminate(bus, PPB_WAIT); 266206268Sdavidch return (error); 267206268Sdavidch} 268206268Sdavidch 269206268Sdavidch/* 270206268Sdavidch * ppb_peripheral_terminate() 271206268Sdavidch * 272206268Sdavidch * Terminate peripheral transfer side 273179771Sdavidch * 274206268Sdavidch * Always return 0 in compatible mode 275206268Sdavidch */ 276206268Sdavidchint 277179771Sdavidchppb_peripheral_terminate(device_t bus, int how) 278179771Sdavidch{ 279207411Sdavidch int error = 0; 280207411Sdavidch 281206268Sdavidch#ifdef DEBUG_1284 282206268Sdavidch printf("t"); 283206268Sdavidch#endif 284206268Sdavidch 285206268Sdavidch ppb_1284_set_state(bus, PPB_PERIPHERAL_TERMINATION); 286179771Sdavidch 287157642Sps /* Event 22 - wait up to host response time (1s) */ 288157642Sps if ((error = do_peripheral_wait(bus, SELECT | nBUSY, 0))) { 289179771Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 22); 290179771Sdavidch goto error; 291206268Sdavidch } 292206268Sdavidch 293206268Sdavidch /* Event 24 */ 294206268Sdavidch ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); 295206268Sdavidch 296206268Sdavidch /* Event 25 - wait up to host response time (1s) */ 297218423Sdavidch if ((error = do_peripheral_wait(bus, nBUSY, nBUSY))) { 298206268Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 25); 299218423Sdavidch goto error; 300218423Sdavidch } 301218423Sdavidch 302206268Sdavidch /* Event 26 */ 303206268Sdavidch ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED)); 304218423Sdavidch DELAY(1); 305157642Sps /* Event 27 */ 306206268Sdavidch ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED)); 307157642Sps 308218423Sdavidch /* Event 28 - wait up to host response time (1s) */ 309206268Sdavidch if ((error = do_peripheral_wait(bus, nBUSY, 0))) { 310206268Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 28); 311206268Sdavidch goto error; 312206268Sdavidch } 313206268Sdavidch 314157642Spserror: 315206268Sdavidch ppb_set_mode(bus, PPB_COMPATIBLE); 316157642Sps ppb_1284_set_state(bus, PPB_FORWARD_IDLE); 317206268Sdavidch 318206268Sdavidch return (0); 319206268Sdavidch} 320206268Sdavidch 321218423Sdavidch/* 322157642Sps * byte_peripheral_outbyte() 323206268Sdavidch * 324206268Sdavidch * Write 1 byte in BYTE mode 325206268Sdavidch */ 326206268Sdavidchstatic int 327218423Sdavidchbyte_peripheral_outbyte(device_t bus, char *buffer, int last) 328157642Sps{ 329206268Sdavidch int error = 0; 330206268Sdavidch 331206268Sdavidch /* Event 7 */ 332206268Sdavidch if ((error = do_1284_wait(bus, nBUSY, nBUSY))) { 333218423Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 7); 334157642Sps goto error; 335206268Sdavidch } 336206268Sdavidch 337206268Sdavidch /* check termination */ 338206268Sdavidch if (!(ppb_rstr(bus) & SELECT)) { 339218423Sdavidch ppb_peripheral_terminate(bus, PPB_WAIT); 340157642Sps goto error; 341218423Sdavidch } 342218423Sdavidch 343206268Sdavidch /* Event 15 - put byte on data lines */ 344206268Sdavidch#ifdef DEBUG_1284 345206268Sdavidch printf("B"); 346157642Sps#endif 347206268Sdavidch ppb_wdtr(bus, *buffer); 348206268Sdavidch 349206268Sdavidch /* Event 9 */ 350206268Sdavidch ppb_wctr(bus, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN)); 351206268Sdavidch 352157642Sps /* Event 10 - wait data read */ 353206268Sdavidch if ((error = do_peripheral_wait(bus, nBUSY, 0))) { 354206268Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 16); 355218423Sdavidch goto error; 356218423Sdavidch } 357206268Sdavidch 358170810Sdavidch /* Event 11 */ 359206268Sdavidch if (!last) { 360206268Sdavidch ppb_wctr(bus, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN)); 361206268Sdavidch } else { 362206268Sdavidch ppb_wctr(bus, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED)); 363206268Sdavidch } 364170810Sdavidch 365206268Sdavidch#if 0 366206268Sdavidch /* Event 16 - wait strobe */ 367218423Sdavidch if ((error = do_peripheral_wait(bus, nACK | nBUSY, 0))) { 368218423Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 16); 369218423Sdavidch goto error; 370170810Sdavidch } 371206268Sdavidch#endif 372206268Sdavidch 373218423Sdavidch /* check termination */ 374218423Sdavidch if (!(ppb_rstr(bus) & SELECT)) { 375206268Sdavidch ppb_peripheral_terminate(bus, PPB_WAIT); 376179771Sdavidch goto error; 377206268Sdavidch } 378206268Sdavidch 379218423Sdavidcherror: 380218423Sdavidch return (error); 381206268Sdavidch} 382179771Sdavidch 383206268Sdavidch/* 384206268Sdavidch * byte_peripheral_write() 385206268Sdavidch * 386206268Sdavidch * Write n bytes in BYTE mode 387218423Sdavidch */ 388170810Sdavidchint 389206268Sdavidchbyte_peripheral_write(device_t bus, char *buffer, int len, int *sent) 390206268Sdavidch{ 391218423Sdavidch int error = 0, i; 392218423Sdavidch char r; 393206268Sdavidch 394170810Sdavidch ppb_1284_set_state(bus, PPB_PERIPHERAL_TRANSFER); 395218423Sdavidch 396218423Sdavidch /* wait forever, the remote host is master and should initiate 397218423Sdavidch * termination 398206268Sdavidch */ 399206268Sdavidch for (i=0; i<len; i++) { 400218423Sdavidch /* force remote nFAULT low to release the remote waiting 401157642Sps * process, if any 402206268Sdavidch */ 403206268Sdavidch r = ppb_rctr(bus); 404206268Sdavidch ppb_wctr(bus, r & ~nINIT); 405206268Sdavidch 406157642Sps#ifdef DEBUG_1284 407157642Sps printf("y"); 408157642Sps#endif 409157642Sps /* Event 7 */ 410206268Sdavidch error = ppb_poll_bus(bus, PPB_FOREVER, nBUSY, nBUSY, 411206268Sdavidch PPB_INTR); 412206268Sdavidch 413157642Sps if (error && error != EWOULDBLOCK) 414157642Sps goto error; 415178132Sdavidch 416206268Sdavidch#ifdef DEBUG_1284 417206268Sdavidch printf("b"); 418206268Sdavidch#endif 419178132Sdavidch if ((error = byte_peripheral_outbyte(bus, buffer+i, (i == len-1)))) 420178132Sdavidch goto error; 421157642Sps } 422206268Sdavidcherror: 423206268Sdavidch if (!error) 424206268Sdavidch ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE); 425157642Sps 426157642Sps *sent = i; 427157642Sps return (error); 428206268Sdavidch} 429206268Sdavidch 430206268Sdavidch/* 431157642Sps * byte_1284_inbyte() 432157642Sps * 433157642Sps * Read 1 byte in BYTE mode 434207411Sdavidch */ 435206268Sdavidchint 436206268Sdavidchbyte_1284_inbyte(device_t bus, char *buffer) 437157642Sps{ 438157642Sps int error = 0; 439157642Sps 440206268Sdavidch /* Event 7 - ready to take data (nAUTO low) */ 441206268Sdavidch ppb_wctr(bus, (PCD | nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); 442206268Sdavidch 443157642Sps /* Event 9 - peripheral set nAck low */ 444157642Sps if ((error = do_1284_wait(bus, nACK, 0))) { 445179771Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 9); 446206268Sdavidch goto error; 447179771Sdavidch } 448179771Sdavidch 449179771Sdavidch /* read the byte */ 450206268Sdavidch *buffer = ppb_rdtr(bus); 451179771Sdavidch 452179771Sdavidch /* Event 10 - data received, can't accept more */ 453179771Sdavidch ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN)); 454206268Sdavidch 455206268Sdavidch /* Event 11 - peripheral ack */ 456179771Sdavidch if ((error = do_1284_wait(bus, nACK, nACK))) { 457179771Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 11); 458179771Sdavidch goto error; 459179771Sdavidch } 460179771Sdavidch 461179771Sdavidch /* Event 16 - strobe */ 462157642Sps ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); 463157642Sps DELAY(3); 464157642Sps ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN)); 465157642Sps 466157642Spserror: 467157642Sps return (error); 468157642Sps} 469157642Sps 470157642Sps/* 471157642Sps * nibble_1284_inbyte() 472157642Sps * 473157642Sps * Read 1 byte in NIBBLE mode 474157642Sps */ 475206268Sdavidchint 476206268Sdavidchnibble_1284_inbyte(device_t bus, char *buffer) 477206268Sdavidch{ 478206268Sdavidch char nibble[2]; 479206268Sdavidch int i, error; 480206268Sdavidch 481206268Sdavidch for (i = 0; i < 2; i++) { 482206268Sdavidch 483206268Sdavidch /* Event 7 - ready to take data (nAUTO low) */ 484206268Sdavidch ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); 485206268Sdavidch 486206268Sdavidch /* Event 8 - peripheral writes the first nibble */ 487206268Sdavidch 488206268Sdavidch /* Event 9 - peripheral set nAck low */ 489206268Sdavidch if ((error = do_1284_wait(bus, nACK, 0))) { 490206268Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 9); 491206268Sdavidch goto error; 492206268Sdavidch } 493206268Sdavidch 494206268Sdavidch /* read nibble */ 495206268Sdavidch nibble[i] = ppb_rstr(bus); 496206268Sdavidch 497206268Sdavidch /* Event 10 - ack, nibble received */ 498206268Sdavidch ppb_wctr(bus, nINIT & ~(AUTOFEED | STROBE | SELECTIN)); 499206268Sdavidch 500206268Sdavidch /* Event 11 - wait ack from peripherial */ 501206268Sdavidch if ((error = do_1284_wait(bus, nACK, nACK))) { 502206268Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 11); 503206268Sdavidch goto error; 504206268Sdavidch } 505206268Sdavidch } 506206268Sdavidch 507206268Sdavidch *buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) | 508206268Sdavidch (nibble2char(nibble[0]) & 0x0f); 509206268Sdavidch 510206268Sdavidcherror: 511206268Sdavidch return (error); 512179771Sdavidch} 513179771Sdavidch 514157642Sps/* 515157642Sps * spp_1284_read() 516157642Sps * 517178132Sdavidch * Read in IEEE1284 NIBBLE/BYTE mode 518176448Sdavidch */ 519157642Spsint 520157642Spsspp_1284_read(device_t bus, int mode, char *buffer, int max, int *read) 521157642Sps{ 522179771Sdavidch int error = 0, len = 0; 523179771Sdavidch int terminate_after_transfer = 1; 524179771Sdavidch int state; 525179771Sdavidch 526157642Sps *read = len = 0; 527157642Sps 528157642Sps state = ppb_1284_get_state(bus); 529157642Sps 530157642Sps switch (state) { 531157642Sps case PPB_FORWARD_IDLE: 532179771Sdavidch if ((error = ppb_1284_negociate(bus, mode, 0))) 533157642Sps return (error); 534157642Sps break; 535157642Sps 536185162Skmacy case PPB_REVERSE_IDLE: 537185162Skmacy terminate_after_transfer = 0; 538182293Sdavidch break; 539182293Sdavidch 540182293Sdavidch default: 541182293Sdavidch ppb_1284_terminate(bus); 542182293Sdavidch if ((error = ppb_1284_negociate(bus, mode, 0))) 543182293Sdavidch return (error); 544182293Sdavidch break; 545182293Sdavidch } 546182293Sdavidch 547185162Skmacy while ((len < max) && !(ppb_rstr(bus) & (nFAULT))) { 548157642Sps 549157642Sps ppb_1284_set_state(bus, PPB_REVERSE_TRANSFER); 550157642Sps 551157642Sps#ifdef DEBUG_1284 552157642Sps printf("B"); 553206268Sdavidch#endif 554206268Sdavidch 555206268Sdavidch switch (mode) { 556206268Sdavidch case PPB_NIBBLE: 557206268Sdavidch /* read a byte, error means no more data */ 558206268Sdavidch if (nibble_1284_inbyte(bus, buffer+len)) 559206268Sdavidch goto end_while; 560157642Sps break; 561206268Sdavidch case PPB_BYTE: 562157642Sps if (byte_1284_inbyte(bus, buffer+len)) 563206268Sdavidch goto end_while; 564157642Sps break; 565157642Sps default: 566157642Sps error = EINVAL; 567206268Sdavidch goto end_while; 568206268Sdavidch } 569206268Sdavidch len ++; 570206268Sdavidch } 571157642Spsend_while: 572206268Sdavidch 573206268Sdavidch if (!error) 574206268Sdavidch ppb_1284_set_state(bus, PPB_REVERSE_IDLE); 575206268Sdavidch 576157642Sps *read = len; 577206268Sdavidch 578206268Sdavidch if (terminate_after_transfer || error) 579157642Sps ppb_1284_terminate(bus); 580206268Sdavidch 581206268Sdavidch return (error); 582206268Sdavidch} 583206268Sdavidch 584206268Sdavidch/* 585206268Sdavidch * ppb_1284_read_id() 586206268Sdavidch * 587206268Sdavidch */ 588206268Sdavidchint 589206268Sdavidchppb_1284_read_id(device_t bus, int mode, char *buffer, 590206268Sdavidch int max, int *read) 591206268Sdavidch{ 592206268Sdavidch int error = 0; 593206268Sdavidch 594206268Sdavidch /* fill the buffer with 0s */ 595157642Sps bzero(buffer, max); 596157642Sps 597157642Sps switch (mode) { 598157642Sps case PPB_NIBBLE: 599206268Sdavidch case PPB_ECP: 600157642Sps if ((error = ppb_1284_negociate(bus, PPB_NIBBLE, PPB_REQUEST_ID))) 601157642Sps return (error); 602157642Sps error = spp_1284_read(bus, PPB_NIBBLE, buffer, max, read); 603157642Sps break; 604157642Sps case PPB_BYTE: 605157642Sps if ((error = ppb_1284_negociate(bus, PPB_BYTE, PPB_REQUEST_ID))) 606157642Sps return (error); 607157642Sps error = spp_1284_read(bus, PPB_BYTE, buffer, max, read); 608157642Sps break; 609157642Sps default: 610157642Sps panic("%s: unsupported mode %d\n", __FUNCTION__, mode); 611157642Sps } 612157642Sps 613157642Sps ppb_1284_terminate(bus); 614206268Sdavidch return (error); 615206268Sdavidch} 616206268Sdavidch 617206268Sdavidch/* 618248036Smarius * ppb_1284_read() 619157642Sps * 620157642Sps * IEEE1284 read 621157642Sps */ 622157642Spsint 623157642Spsppb_1284_read(device_t bus, int mode, char *buffer, 624157642Sps int max, int *read) 625157642Sps{ 626157642Sps int error = 0; 627157642Sps 628157642Sps switch (mode) { 629157642Sps case PPB_NIBBLE: 630157642Sps case PPB_BYTE: 631157642Sps error = spp_1284_read(bus, mode, buffer, max, read); 632157642Sps break; 633157642Sps default: 634157642Sps return (EINVAL); 635157642Sps } 636157642Sps 637157642Sps return (error); 638157642Sps} 639157642Sps 640157642Sps/* 641157642Sps * ppb_1284_negociate() 642157642Sps * 643157642Sps * IEEE1284 negociation phase 644157642Sps * 645157642Sps * Normal nibble mode or request device id mode (see ppb_1284.h) 646157642Sps * 647157642Sps * After negociation, nFAULT is low if data is available 648157642Sps */ 649157642Spsint 650157642Spsppb_1284_negociate(device_t bus, int mode, int options) 651157642Sps{ 652157642Sps int error; 653157642Sps int request_mode; 654157642Sps 655157642Sps#ifdef DEBUG_1284 656157642Sps printf("n"); 657157642Sps#endif 658157642Sps 659157642Sps if (ppb_1284_get_state(bus) >= PPB_PERIPHERAL_NEGOCIATION) 660206268Sdavidch ppb_peripheral_terminate(bus, PPB_WAIT); 661206268Sdavidch 662206268Sdavidch if (ppb_1284_get_state(bus) != PPB_FORWARD_IDLE) 663206268Sdavidch ppb_1284_terminate(bus); 664206268Sdavidch 665157642Sps#ifdef DEBUG_1284 666206268Sdavidch printf("%d", mode); 667157642Sps#endif 668157642Sps 669206268Sdavidch /* ensure the host is in compatible mode */ 670206268Sdavidch ppb_set_mode(bus, PPB_COMPATIBLE); 671157642Sps 672206268Sdavidch /* reset error to catch the actual negociation error */ 673206268Sdavidch ppb_1284_reset_error(bus, PPB_FORWARD_IDLE); 674206268Sdavidch 675206268Sdavidch /* calculate ext. value */ 676157642Sps request_mode = ppb_request_mode(mode, options); 677157642Sps 678206268Sdavidch /* default state */ 679157642Sps ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); 680157642Sps DELAY(1); 681206268Sdavidch 682157642Sps /* enter negociation phase */ 683157642Sps ppb_1284_set_state(bus, PPB_NEGOCIATION); 684206268Sdavidch 685206268Sdavidch /* Event 0 - put the exten. value on the data lines */ 686179771Sdavidch ppb_wdtr(bus, request_mode); 687206268Sdavidch 688179771Sdavidch#ifdef PERIPH_1284 689206268Sdavidch /* request remote host attention */ 690206268Sdavidch ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); 691157642Sps DELAY(1); 692206268Sdavidch ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN)); 693206268Sdavidch#else 694206268Sdavidch DELAY(1); 695157642Sps 696206268Sdavidch#endif /* !PERIPH_1284 */ 697157642Sps 698157642Sps /* Event 1 - enter IEEE1284 mode */ 699157642Sps ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); 700157642Sps 701157642Sps#ifdef PERIPH_1284 702157642Sps /* ignore the PError line, wait a bit more, remote host's 703157642Sps * interrupts don't respond fast enough */ 704179771Sdavidch if (ppb_poll_bus(bus, 40, nACK | SELECT | nFAULT, 705179771Sdavidch SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) { 706206268Sdavidch ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2); 707179771Sdavidch error = ENODEV; 708157642Sps goto error; 709157642Sps } 710157642Sps#else 711157642Sps /* Event 2 - trying IEEE1284 dialog */ 712248036Smarius if (do_1284_wait(bus, nACK | PERROR | SELECT | nFAULT, 713157642Sps PERROR | SELECT | nFAULT)) { 714157642Sps ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2); 715157642Sps error = ENODEV; 716157642Sps goto error; 717157642Sps } 718157642Sps#endif /* !PERIPH_1284 */ 719157642Sps 720157642Sps /* Event 3 - latch the ext. value to the peripheral */ 721157642Sps ppb_wctr(bus, (nINIT | STROBE | AUTOFEED) & ~SELECTIN); 722179771Sdavidch DELAY(1); 723157642Sps 724157642Sps /* Event 4 - IEEE1284 device recognized */ 725179771Sdavidch ppb_wctr(bus, nINIT & ~(SELECTIN | AUTOFEED | STROBE)); 726157642Sps 727157642Sps /* Event 6 - waiting for status lines */ 728157642Sps if (do_1284_wait(bus, nACK, nACK)) { 729179771Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 6); 730157642Sps error = EBUSY; 731157642Sps goto error; 732157642Sps } 733157642Sps 734179771Sdavidch /* Event 7 - quering result consider nACK not to misunderstand 735157642Sps * a remote computer terminate sequence */ 736206268Sdavidch if (options & PPB_EXTENSIBILITY_LINK) { 737157642Sps 738157642Sps /* XXX not fully supported yet */ 739206268Sdavidch ppb_1284_terminate(bus); 740157642Sps return (0); 741157642Sps 742206268Sdavidch } 743206268Sdavidch if (request_mode == NIBBLE_1284_NORMAL) { 744206268Sdavidch if (do_1284_wait(bus, nACK | SELECT, nACK)) { 745206268Sdavidch ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7); 746206268Sdavidch error = ENODEV; 747157642Sps goto error; 748206268Sdavidch } 749206268Sdavidch } else { 750206268Sdavidch if (do_1284_wait(bus, nACK | SELECT, SELECT | nACK)) { 751157642Sps ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7); 752170810Sdavidch error = ENODEV; 753170810Sdavidch goto error; 754157642Sps } 755206268Sdavidch } 756206268Sdavidch 757206268Sdavidch switch (mode) { 758206268Sdavidch case PPB_NIBBLE: 759206268Sdavidch case PPB_PS2: 760157642Sps /* enter reverse idle phase */ 761206268Sdavidch ppb_1284_set_state(bus, PPB_REVERSE_IDLE); 762157642Sps break; 763157642Sps case PPB_ECP: 764157642Sps /* negociation ok, now setup the communication */ 765157642Sps ppb_1284_set_state(bus, PPB_SETUP); 766157642Sps ppb_wctr(bus, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE)); 767206268Sdavidch 768206268Sdavidch#ifdef PERIPH_1284 769157642Sps /* ignore PError line */ 770157642Sps if (do_1284_wait(bus, nACK | SELECT | nBUSY, 771206268Sdavidch nACK | SELECT | nBUSY)) { 772157642Sps ppb_1284_set_error(bus, PPB_TIMEOUT, 30); 773206268Sdavidch error = ENODEV; 774157642Sps goto error; 775157642Sps } 776157642Sps#else 777157642Sps if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY, 778157642Sps nACK | SELECT | PERROR | nBUSY)) { 779206268Sdavidch ppb_1284_set_error(bus, PPB_TIMEOUT, 30); 780157642Sps error = ENODEV; 781206268Sdavidch goto error; 782157642Sps } 783157642Sps#endif /* !PERIPH_1284 */ 784157642Sps 785157642Sps /* ok, the host enters the ForwardIdle state */ 786157642Sps ppb_1284_set_state(bus, PPB_ECP_FORWARD_IDLE); 787157642Sps break; 788157642Sps case PPB_EPP: 789157642Sps ppb_1284_set_state(bus, PPB_EPP_IDLE); 790157642Sps break; 791157642Sps 792157642Sps default: 793157642Sps panic("%s: unknown mode (%d)!", __FUNCTION__, mode); 794157642Sps } 795157642Sps ppb_set_mode(bus, mode); 796157642Sps 797157642Sps return (0); 798157642Sps 799157642Spserror: 800157642Sps ppb_1284_terminate(bus); 801157642Sps 802157642Sps return (error); 803157642Sps} 804157642Sps 805157642Sps/* 806157642Sps * ppb_1284_terminate() 807157642Sps * 808171667Sdavidch * IEEE1284 termination phase, return code should ignored since the host 809235818Syongari * is _always_ in compatible mode after ppb_1284_terminate() 810235818Syongari */ 811235818Syongariint 812235818Syongarippb_1284_terminate(device_t bus) 813235818Syongari{ 814235818Syongari 815235818Syongari#ifdef DEBUG_1284 816235818Syongari printf("T"); 817235818Syongari#endif 818235818Syongari 819235818Syongari /* do not reset error here to keep the error that 820235818Syongari * may occured before the ppb_1284_terminate() call */ 821235818Syongari ppb_1284_set_state(bus, PPB_TERMINATION); 822235818Syongari 823235818Syongari#ifdef PERIPH_1284 824235818Syongari /* request remote host attention */ 825235818Syongari ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED)); 826171667Sdavidch DELAY(1); 827171667Sdavidch#endif /* PERIPH_1284 */ 828157642Sps 829157642Sps /* Event 22 - set nSelectin low and nAutoFeed high */ 830157642Sps ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); 831157642Sps 832157642Sps /* Event 24 - waiting for peripheral, Xflag ignored */ 833157642Sps if (do_1284_wait(bus, nACK | nBUSY | nFAULT, nFAULT)) { 834157642Sps ppb_1284_set_error(bus, PPB_TIMEOUT, 24); 835157642Sps goto error; 836157642Sps } 837157642Sps 838157642Sps /* Event 25 - set nAutoFd low */ 839157642Sps ppb_wctr(bus, (nINIT | SELECTIN | AUTOFEED) & ~STROBE); 840157642Sps 841157642Sps /* Event 26 - compatible mode status is set */ 842157642Sps 843157642Sps /* Event 27 - peripheral set nAck high */ 844157642Sps if (do_1284_wait(bus, nACK, nACK)) { 845157642Sps ppb_1284_set_error(bus, PPB_TIMEOUT, 27); 846157642Sps } 847157642Sps 848157642Sps /* Event 28 - end termination, return to idle phase */ 849157642Sps ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); 850157642Sps 851157642Spserror: 852157642Sps /* return to compatible mode */ 853157642Sps ppb_set_mode(bus, PPB_COMPATIBLE); 854157642Sps ppb_1284_set_state(bus, PPB_FORWARD_IDLE); 855206268Sdavidch 856157642Sps return (0); 857206268Sdavidch} 858157642Sps