123245Smckusick /* 2*35052Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 323245Smckusick * All rights reserved. The Berkeley software License Agreement 423245Smckusick * specifies the terms and conditions for redistribution. 523245Smckusick * 6*35052Skarels * @(#)ts.c 7.5 (Berkeley) 07/09/88 723245Smckusick */ 83268Swnj 93268Swnj /* 103268Swnj * TS11 tape driver 113268Swnj */ 123268Swnj 1333408Skarels #include "param.h" 1433408Skarels #include "inode.h" 1533408Skarels #include "fs.h" 169186Ssam 17*35052Skarels #include "../vax/pte.h" 18*35052Skarels 199186Ssam #include "../vaxuba/tsreg.h" 209186Ssam #include "../vaxuba/ubareg.h" 219186Ssam 223268Swnj #include "saio.h" 233268Swnj #include "savax.h" 243268Swnj 2533532Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 2633532Sbostic u_short tsstd[MAXCTLR] = { 0772520 }; 273268Swnj 283268Swnj struct iob ctsbuf; 293268Swnj 303268Swnj u_short ts_uba; /* Unibus address of ts structure */ 313268Swnj 323268Swnj struct ts { 333268Swnj struct ts_cmd ts_cmd; 343268Swnj struct ts_char ts_char; 353268Swnj struct ts_sts ts_sts; 363268Swnj } ts; 373268Swnj 383268Swnj tsopen(io) 393268Swnj register struct iob *io; 403268Swnj { 413268Swnj static struct ts *ts_ubaddr; 4233532Sbostic register struct tsdevice *tsaddr; 433344Swnj long i = 0; 443268Swnj 45*35052Skarels if ((u_int)io->i_adapt >= nuba) 46*35052Skarels return (EADAPT); 4733532Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 4833532Sbostic return (ECTLR); 4933532Sbostic /* TS11 only supports one transport per formatter */ 50*35052Skarels if (io->i_unit) 5133532Sbostic return(EUNIT); 5233532Sbostic tsaddr = (struct tsdevice *)ubamem(io->i_adapt, tsstd[io->i_ctlr]); 5333532Sbostic if (badaddr((char *)tsaddr, sizeof (short))) 5433408Skarels return (ENXIO); 553344Swnj tsaddr->tssr = 0; 563344Swnj while ((tsaddr->tssr & TS_SSR)==0) { 577447Sroot DELAY(10); 583344Swnj if (++i > 1000000) { 593344Swnj printf("ts: not ready\n"); 6033532Sbostic return (ENXIO); 613268Swnj } 623268Swnj } 633268Swnj if (tsaddr->tssr&TS_OFL) { 643268Swnj printf("ts: offline\n"); 6533532Sbostic return (ENXIO); 663268Swnj } 673268Swnj if (tsaddr->tssr&TS_NBA) { 683344Swnj int i; 693344Swnj 703268Swnj ctsbuf.i_ma = (caddr_t) &ts; 713268Swnj ctsbuf.i_cc = sizeof(ts); 723268Swnj if (ts_ubaddr == 0) 733344Swnj ts_ubaddr = (struct ts *)ubasetup(&ctsbuf, 2); 743344Swnj ts_uba = (u_short)((long)ts_ubaddr + (((long)ts_ubaddr>>16)&03)); 753268Swnj ts.ts_char.char_addr = (int)&ts_ubaddr->ts_sts; 763268Swnj ts.ts_char.char_size = sizeof(ts.ts_sts); 773344Swnj ts.ts_char.char_mode = TS_ESS; 783344Swnj ts.ts_cmd.c_cmd = TS_ACK|TS_SETCHR; 793344Swnj i = (int)&ts_ubaddr->ts_char; 803344Swnj ts.ts_cmd.c_loba = i; 813344Swnj ts.ts_cmd.c_hiba = (i>>16)&3; 823268Swnj ts.ts_cmd.c_size = sizeof(ts.ts_char); 833268Swnj tsaddr->tsdb = ts_uba; 843268Swnj } 853268Swnj tsstrategy(io, TS_REW); 8633532Sbostic if (io->i_cc = io->i_part) 873268Swnj tsstrategy(io, TS_SFORWF); 8833408Skarels return (0); 893268Swnj } 903268Swnj 913268Swnj tsclose(io) 923268Swnj register struct iob *io; 933268Swnj { 943268Swnj tsstrategy(io, TS_REW); 953268Swnj } 963268Swnj 973268Swnj tsstrategy(io, func) 983268Swnj register struct iob *io; 993268Swnj { 10033532Sbostic register struct tsdevice *tsaddr; 10133532Sbostic register int errcnt, info; 1023268Swnj 10333532Sbostic tsaddr = (struct tsdevice *)ubamem(io->i_adapt, tsstd[io->i_ctlr]); 10433532Sbostic errcnt = info = 0; 1053268Swnj retry: 1063268Swnj while ((tsaddr->tssr & TS_SSR) == 0) 1073344Swnj DELAY(100); 1083344Swnj if (func == TS_REW || func == TS_SFORWF) 1093344Swnj ts.ts_cmd.c_repcnt = io->i_cc; 1103344Swnj else { 1113344Swnj info = ubasetup(io, 1); 1123344Swnj ts.ts_cmd.c_size = io->i_cc; 1133344Swnj ts.ts_cmd.c_loba = info; 1143344Swnj ts.ts_cmd.c_hiba = (info>>16)&3; 11533532Sbostic if (func == READ) 11633532Sbostic func = TS_RCOM; 11733532Sbostic else if (func == WRITE) 11833532Sbostic func = TS_WCOM; 1193344Swnj } 1203268Swnj ts.ts_cmd.c_cmd = TS_ACK|TS_CVC|func; 1213268Swnj tsaddr->tsdb = ts_uba; 1223344Swnj do 1233344Swnj DELAY(100) 1243344Swnj while ((tsaddr->tssr & TS_SSR) == 0); 1253344Swnj if (info) 1263344Swnj ubafree(io, info); 1273344Swnj if (ts.ts_sts.s_xs0 & TS_TMK) 1283268Swnj return (0); 1293268Swnj if (tsaddr->tssr & TS_SC) { 1307447Sroot printf("ts tape error: er=%b, xs0=%b\n", 1313349Swnj tsaddr->tssr, TSSR_BITS, 1323349Swnj ts.ts_sts.s_xs0, TSXS0_BITS); 13333532Sbostic if (errcnt++ == 10) { 1343349Swnj printf("ts: unrecovered error\n"); 1353268Swnj return (-1); 1363268Swnj } 1373268Swnj if (func == TS_RCOM || func == TS_WCOM) 1383268Swnj func |= TS_RETRY; 1393268Swnj goto retry; 1403268Swnj } 1413268Swnj if (errcnt) 1423349Swnj printf("ts: recovered by retry\n"); 1433268Swnj return (io->i_cc - ts.ts_sts.s_rbpcr); 1443268Swnj } 145