1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* dspWrite.c 29 * From Mike Shoemaker v01.13 06/21/90 mbs for MacOS 30 */ 31/* 32 * Change log: 33 * 06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen) 34 * 09/07/95 - Modified for performance (Tuyen Nguyen) 35 * Modified for MP, 1996 by Tuyen Nguyen 36 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX. 37 */ 38 39#include <sys/errno.h> 40#include <sys/types.h> 41#include <sys/param.h> 42#include <machine/spl.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/proc.h> 46#include <sys/filedesc.h> 47#include <sys/fcntl.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50 51#include <netat/sysglue.h> 52#include <netat/appletalk.h> 53#include <netat/at_pcb.h> 54#include <netat/debug.h> 55#include <netat/adsp.h> 56#include <netat/adsp_internal.h> 57 58 59int FillSendQueue(CCBPtr, struct adspcmd *); 60 61/* 62 * FillSendQueue 63 * 64 * INPUTS: 65 * sp stream 66 * OUTPUTS: 67 * none 68 */ 69int FillSendQueue( /* (CCBPtr sp) */ 70 register CCBPtr sp, 71 register struct adspcmd *pb) /* The write PB we're playing with */ 72{ 73 gbuf_t *mb, *nmb; 74 int eom; /* True if should set eom in header */ 75 int cnt; /* # of bytes in this write */ 76 int err = 0; 77 78 cnt = pb->u.ioParams.reqCount - pb->u.ioParams.actCount; 79 eom = pb->u.ioParams.eom ? F_EOM : 0; 80 81 if (cnt == 0 && eom == 0) /* Nothing to do here, complete it */ 82 goto unlink; 83 84 /* The 1st mbuf in the pb->mp chain (mb) is the adspcmd structure. 85 The 2nd mbuf (nmb) will be the beginning of the data. */ 86 mb = pb->mp; 87 nmb = gbuf_cont(mb); 88 if (gbuf_len(mb) > sizeof(struct adspcmd)) { 89 if ((nmb = gbuf_dupb(mb)) == 0) { 90 gbuf_wset(mb,sizeof(struct adspcmd)); 91 err = errDSPQueueSize; 92 goto unlink; 93 } 94 gbuf_wset(mb,sizeof(struct adspcmd)); 95 gbuf_rinc(nmb,sizeof(struct adspcmd)); 96 gbuf_cont(nmb) = gbuf_cont(mb); 97 } else if (nmb == 0) { 98 if ((nmb = gbuf_alloc(1, PRI_LO)) == 0) { 99 err = errENOBUFS; 100 goto unlink; 101 } 102 } 103 gbuf_cont(mb) = 0; 104 105 sp->sData = 1; /* note that there is data to send */ 106 if ((mb = sp->csbuf_mb)) { /* add to the current message */ 107 gbuf_linkb(mb, nmb); 108 } else 109 sp->csbuf_mb = nmb; /* mark the buffer we are currently filling */ 110 if (eom) { 111 if ((mb = sp->sbuf_mb)) { 112 while (gbuf_next(mb)) 113 mb = gbuf_next(mb); 114 gbuf_next(mb) = sp->csbuf_mb; /* add the current item */ 115 } else 116 sp->sbuf_mb = sp->csbuf_mb; 117 sp->csbuf_mb = 0; /* if its done, no current buffer */ 118 } 119 pb->u.ioParams.actCount += cnt; /* Update count field in param blk */ 120 121 if (pb->u.ioParams.actCount == pb->u.ioParams.reqCount) { 122 /* Write is complete */ 123unlink: 124 if (pb->u.ioParams.flush) /* flush the send Q? */ 125 sp->writeFlush = 1; 126 127 pb->ioResult = err; 128 if (err) 129 atalk_notify(sp->gref, EIO); 130 gbuf_freem(pb->mp); 131 } 132 133 return 0; 134} /* FillSendQueue */ 135 136/* 137 * dspWrite 138 * 139 * INPUTS: 140 * --> ccbRefNum refnum of connection end 141 * --> reqCount requested number of bytes to write 142 * --> dataPtr pointer to buffer for reading bytes into 143 * --> eom one if end-of-message, zero otherwise 144 * 145 * OUTPUTS: 146 * <-- actCount actual number of bytes written 147 * 148 * ERRORS: 149 * errRefNum bad connection refnum 150 * errState connection is not open 151 * errAborted request aborted by Remove or Close call 152 */ 153int adspWrite(sp, pb) /* (DSPPBPtr pb) */ 154 CCBPtr sp; 155 struct adspcmd *pb; 156{ 157 158 if (sp == 0) { 159 pb->ioResult = errRefNum; 160 return EINVAL; /* no stream, so drop the message */ 161 } 162 163 if (sp->state != sOpen) { /* Not allowed */ 164 pb->ioResult = errState; 165 atalk_notify(sp->gref, ENOTCONN); 166 gbuf_freem(pb->mp); 167 return 0; 168 } 169 170 pb->u.ioParams.actCount = 0; /* Set # of bytes so far to zero */ 171 172 FillSendQueue(sp, pb); /* Copy from write param block to send queue */ 173 174 CheckSend(sp); /* See if we should send anything */ 175 return 0; 176} 177 178#ifdef notdef 179int adsp_check = 1; 180 181CheckQueue(sp) 182 CCBPtr sp; 183{ 184 register gbuf_t *mp, *tmp; 185 unsigned char current; 186 int current_valid = 0; 187 188 if (adsp_check == 0) 189 return; 190 if (mp = sp->sbuf_mb) { 191 current = *mp->b_rptr; 192 current_valid = 1; 193 while (mp) { 194 tmp = mp; 195 while (tmp) { 196 current = CheckData(tmp->b_rptr, tmp->b_wptr - tmp->b_rptr, 197 current); 198 tmp = tmp->b_cont; 199 } 200 mp = mp->b_next; 201 } 202 } 203 if (mp = sp->csbuf_mb) { 204 if (current_valid == 0) 205 current = *mp->b_rptr; 206 tmp = mp; 207 while (tmp) { 208 current = CheckData(tmp->b_rptr, tmp->b_wptr - tmp->b_rptr, 209 current); 210 tmp = tmp->b_cont; 211 } 212 } 213} 214 215 216int adsp_bad_block_count; 217char *adsp_bad_block; 218 219CheckData(block, size, current) 220 char *block; 221 int size; 222 u_char current; 223{ 224 register int anError = 0; 225 register int i; 226 227 for (i = 0; i < size; i++) { 228 if ((block[i] & 0xff) != (current & 0xff)) { 229 if (!anError) { 230 adsp_bad_block = block; 231 } 232 anError++; 233 } 234 current++; 235 } 236 237 if (anError) { 238 adsp_bad_block_count++; 239 } 240 return current; 241} 242#endif 243